jscript: Add missing port.h include for isnan.
[wine/multimedia.git] / dlls / crypt32 / encode.c
blob75900124601282a3925c8f25f1cce3836e5e14cc
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, pbEncoded ? *pcbEncoded : 0);
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, %d\n", entry, pbEncoded, pbEncoded ? *pcbEncoded : 0);
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, pbEncoded ? *pcbEncoded : 0);
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 if (value->Value.cbData)
1016 strLen = value->Value.cbData / sizeof(WCHAR);
1017 else if (str)
1018 strLen = strlenW(str);
1019 else
1020 strLen = 0;
1021 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
1022 NULL);
1023 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1024 bytesNeeded = 1 + lenBytes + encodedLen;
1025 if (!pbEncoded)
1026 *pcbEncoded = bytesNeeded;
1027 else
1029 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1030 pbEncoded, pcbEncoded, bytesNeeded)))
1032 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1033 pbEncoded = *(BYTE **)pbEncoded;
1034 *pbEncoded++ = ASN_UTF8STRING;
1035 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1036 pbEncoded += lenBytes;
1037 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
1038 bytesNeeded - lenBytes - 1, NULL, NULL);
1041 return ret;
1044 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
1045 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1046 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1048 BOOL ret = TRUE;
1050 __TRY
1052 const CERT_NAME_VALUE *value = pvStructInfo;
1054 switch (value->dwValueType)
1056 case CERT_RDN_ANY_TYPE:
1057 /* explicitly disallowed */
1058 SetLastError(E_INVALIDARG);
1059 ret = FALSE;
1060 break;
1061 case CERT_RDN_ENCODED_BLOB:
1062 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
1063 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1064 break;
1065 case CERT_RDN_OCTET_STRING:
1066 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1067 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1068 break;
1069 case CERT_RDN_NUMERIC_STRING:
1070 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1071 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1072 break;
1073 case CERT_RDN_PRINTABLE_STRING:
1074 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1075 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1076 break;
1077 case CERT_RDN_TELETEX_STRING:
1078 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1079 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1080 break;
1081 case CERT_RDN_VIDEOTEX_STRING:
1082 ret = CRYPT_AsnEncodeStringCoerce(value,
1083 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1084 break;
1085 case CERT_RDN_IA5_STRING:
1086 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1087 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1088 break;
1089 case CERT_RDN_GRAPHIC_STRING:
1090 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1091 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1092 break;
1093 case CERT_RDN_VISIBLE_STRING:
1094 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1095 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1096 break;
1097 case CERT_RDN_GENERAL_STRING:
1098 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1099 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1100 break;
1101 case CERT_RDN_UNIVERSAL_STRING:
1102 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1103 SetLastError(CRYPT_E_ASN1_CHOICE);
1104 ret = FALSE;
1105 break;
1106 case CERT_RDN_BMP_STRING:
1107 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1108 pbEncoded, pcbEncoded);
1109 break;
1110 case CERT_RDN_UTF8_STRING:
1111 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1112 pbEncoded, pcbEncoded);
1113 break;
1114 default:
1115 SetLastError(CRYPT_E_ASN1_CHOICE);
1116 ret = FALSE;
1119 __EXCEPT_PAGE_FAULT
1121 SetLastError(STATUS_ACCESS_VIOLATION);
1122 ret = FALSE;
1124 __ENDTRY
1125 return ret;
1128 static BOOL CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1129 const CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1130 BYTE *pbEncoded, DWORD *pcbEncoded)
1132 DWORD bytesNeeded = 0, lenBytes, size;
1133 BOOL ret;
1135 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1136 0, NULL, NULL, &size);
1137 if (ret)
1139 bytesNeeded += size;
1140 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1141 * with dwValueType, so "cast" it to get its encoded size
1143 ret = nameValueEncodeFunc(dwCertEncodingType, NULL, &attr->dwValueType,
1144 0, NULL, NULL, &size);
1145 if (ret)
1147 bytesNeeded += size;
1148 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1149 bytesNeeded += 1 + lenBytes;
1150 if (pbEncoded)
1152 if (*pcbEncoded < bytesNeeded)
1154 SetLastError(ERROR_MORE_DATA);
1155 ret = FALSE;
1157 else
1159 *pbEncoded++ = ASN_SEQUENCE;
1160 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1161 &lenBytes);
1162 pbEncoded += lenBytes;
1163 size = bytesNeeded - 1 - lenBytes;
1164 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1165 attr->pszObjId, 0, NULL, pbEncoded, &size);
1166 if (ret)
1168 pbEncoded += size;
1169 size = bytesNeeded - 1 - lenBytes - size;
1170 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1171 &attr->dwValueType, 0, NULL, pbEncoded, &size);
1172 if (!ret)
1173 *pcbEncoded = size;
1177 if (ret)
1178 *pcbEncoded = bytesNeeded;
1180 else
1182 /* Have to propagate index of failing character */
1183 *pcbEncoded = size;
1186 return ret;
1189 static int BLOBComp(const void *l, const void *r)
1191 const CRYPT_DER_BLOB *a = l, *b = r;
1192 int ret;
1194 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1195 ret = a->cbData - b->cbData;
1196 return ret;
1199 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1201 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1202 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1203 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1205 const CRYPT_BLOB_ARRAY *set = pvStructInfo;
1206 DWORD bytesNeeded = 0, lenBytes, i;
1207 BOOL ret;
1209 for (i = 0; i < set->cBlob; i++)
1210 bytesNeeded += set->rgBlob[i].cbData;
1211 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1212 bytesNeeded += 1 + lenBytes;
1213 if (!pbEncoded)
1215 *pcbEncoded = bytesNeeded;
1216 ret = TRUE;
1218 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1219 pbEncoded, pcbEncoded, bytesNeeded)))
1221 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1222 pbEncoded = *(BYTE **)pbEncoded;
1223 qsort(set->rgBlob, set->cBlob, sizeof(CRYPT_DER_BLOB), BLOBComp);
1224 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1225 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1226 pbEncoded += lenBytes;
1227 for (i = 0; i < set->cBlob; i++)
1229 memcpy(pbEncoded, set->rgBlob[i].pbData, set->rgBlob[i].cbData);
1230 pbEncoded += set->rgBlob[i].cbData;
1233 return ret;
1236 struct DERSetDescriptor
1238 DWORD cItems;
1239 const void *items;
1240 size_t itemSize;
1241 size_t itemOffset;
1242 CryptEncodeObjectExFunc encode;
1245 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,
1246 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1247 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1249 const struct DERSetDescriptor *desc = pvStructInfo;
1250 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1251 BOOL ret = TRUE;
1252 DWORD i;
1254 if (desc->cItems)
1256 setOf.rgBlob = CryptMemAlloc(desc->cItems * sizeof(CRYPT_DER_BLOB));
1257 if (!setOf.rgBlob)
1258 ret = FALSE;
1259 else
1261 setOf.cBlob = desc->cItems;
1262 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1265 for (i = 0; ret && i < setOf.cBlob; i++)
1267 ret = desc->encode(dwCertEncodingType, lpszStructType,
1268 (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
1269 0, NULL, NULL, &setOf.rgBlob[i].cbData);
1270 if (ret)
1272 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1273 if (!setOf.rgBlob[i].pbData)
1274 ret = FALSE;
1275 else
1276 ret = desc->encode(dwCertEncodingType, lpszStructType,
1277 (const BYTE *)desc->items + i * desc->itemSize +
1278 desc->itemOffset, 0, NULL, setOf.rgBlob[i].pbData,
1279 &setOf.rgBlob[i].cbData);
1281 /* Some functions propagate their errors through the size */
1282 if (!ret)
1283 *pcbEncoded = setOf.rgBlob[i].cbData;
1285 if (ret)
1287 DWORD bytesNeeded = 0, lenBytes;
1289 for (i = 0; i < setOf.cBlob; i++)
1290 bytesNeeded += setOf.rgBlob[i].cbData;
1291 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1292 bytesNeeded += 1 + lenBytes;
1293 if (!pbEncoded)
1294 *pcbEncoded = bytesNeeded;
1295 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1296 pbEncoded, pcbEncoded, bytesNeeded)))
1298 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1299 pbEncoded = *(BYTE **)pbEncoded;
1300 qsort(setOf.rgBlob, setOf.cBlob, sizeof(CRYPT_DER_BLOB),
1301 BLOBComp);
1302 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1303 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1304 pbEncoded += lenBytes;
1305 for (i = 0; i < setOf.cBlob; i++)
1307 memcpy(pbEncoded, setOf.rgBlob[i].pbData,
1308 setOf.rgBlob[i].cbData);
1309 pbEncoded += setOf.rgBlob[i].cbData;
1313 for (i = 0; i < setOf.cBlob; i++)
1314 CryptMemFree(setOf.rgBlob[i].pbData);
1315 CryptMemFree(setOf.rgBlob);
1316 return ret;
1319 static BOOL CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, const CERT_RDN *rdn,
1320 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1321 DWORD *pcbEncoded)
1323 BOOL ret;
1324 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1326 __TRY
1328 DWORD i;
1330 ret = TRUE;
1331 if (rdn->cRDNAttr)
1333 setOf.rgBlob = CryptMemAlloc(rdn->cRDNAttr *
1334 sizeof(CRYPT_DER_BLOB));
1335 if (!setOf.rgBlob)
1336 ret = FALSE;
1337 else
1339 setOf.cBlob = rdn->cRDNAttr;
1340 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1343 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1345 setOf.rgBlob[i].cbData = 0;
1346 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1347 nameValueEncodeFunc, NULL, &setOf.rgBlob[i].cbData);
1348 if (ret)
1350 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1351 if (!setOf.rgBlob[i].pbData)
1352 ret = FALSE;
1353 else
1354 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1355 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1356 setOf.rgBlob[i].pbData, &setOf.rgBlob[i].cbData);
1358 if (!ret)
1360 /* Have to propagate index of failing character */
1361 *pcbEncoded = setOf.rgBlob[i].cbData;
1364 if (ret)
1365 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1366 pbEncoded, pcbEncoded);
1367 for (i = 0; i < setOf.cBlob; i++)
1368 CryptMemFree(setOf.rgBlob[i].pbData);
1370 __EXCEPT_PAGE_FAULT
1372 SetLastError(STATUS_ACCESS_VIOLATION);
1373 ret = FALSE;
1375 __ENDTRY
1376 CryptMemFree(setOf.rgBlob);
1377 return ret;
1380 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1381 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1382 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1384 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1385 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1386 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1387 DWORD *pcbEncoded)
1389 const CERT_NAME_VALUE *value = pvStructInfo;
1390 BOOL ret;
1392 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1393 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1394 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1395 else
1396 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1397 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1398 return ret;
1401 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1402 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1403 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1405 BOOL ret = TRUE;
1407 __TRY
1409 const CERT_NAME_INFO *info = pvStructInfo;
1410 DWORD bytesNeeded = 0, lenBytes, size, i;
1412 TRACE("encoding name with %d RDNs\n", info->cRDN);
1413 ret = TRUE;
1414 for (i = 0; ret && i < info->cRDN; i++)
1416 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1417 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1418 if (ret)
1419 bytesNeeded += size;
1420 else
1421 *pcbEncoded = size;
1423 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1424 bytesNeeded += 1 + lenBytes;
1425 if (ret)
1427 if (!pbEncoded)
1428 *pcbEncoded = bytesNeeded;
1429 else
1431 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1432 pbEncoded, pcbEncoded, bytesNeeded)))
1434 BYTE *out;
1436 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1437 pbEncoded = *(BYTE **)pbEncoded;
1438 out = pbEncoded;
1439 *out++ = ASN_SEQUENCEOF;
1440 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
1441 out += lenBytes;
1442 for (i = 0; ret && i < info->cRDN; i++)
1444 size = bytesNeeded;
1445 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1446 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1447 out, &size);
1448 if (ret)
1450 out += size;
1451 bytesNeeded -= size;
1453 else
1454 *pcbEncoded = size;
1456 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1457 CRYPT_FreeSpace(pEncodePara, pbEncoded);
1462 __EXCEPT_PAGE_FAULT
1464 SetLastError(STATUS_ACCESS_VIOLATION);
1465 ret = FALSE;
1467 __ENDTRY
1468 return ret;
1471 static BOOL WINAPI CRYPT_AsnEncodeCTLVersion(DWORD dwCertEncodingType,
1472 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1473 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1475 const DWORD *ver = pvStructInfo;
1476 BOOL ret;
1478 /* CTL_V1 is not encoded */
1479 if (*ver == CTL_V1)
1481 *pcbEncoded = 0;
1482 ret = TRUE;
1484 else
1485 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
1486 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1487 return ret;
1490 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
1491 * if they are empty and the OID is not empty (otherwise omits them.)
1493 static BOOL WINAPI CRYPT_AsnEncodeCTLSubjectAlgorithm(
1494 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1495 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1496 DWORD *pcbEncoded)
1498 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
1499 BOOL ret;
1500 struct AsnEncodeSequenceItem items[2] = {
1501 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
1503 DWORD cItem = 1;
1505 if (algo->pszObjId)
1507 static const BYTE asn1Null[] = { ASN_NULL, 0 };
1508 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
1509 (LPBYTE)asn1Null };
1511 if (algo->Parameters.cbData)
1512 items[cItem].pvStructInfo = &algo->Parameters;
1513 else
1514 items[cItem].pvStructInfo = &nullBlob;
1515 items[cItem].encodeFunc = CRYPT_CopyEncodedBlob;
1516 cItem++;
1518 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1519 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1520 return ret;
1523 static BOOL CRYPT_AsnEncodeCTLEntry(const CTL_ENTRY *entry,
1524 BYTE *pbEncoded, DWORD *pcbEncoded)
1526 struct AsnEncodeSequenceItem items[2] = {
1527 { &entry->SubjectIdentifier, CRYPT_AsnEncodeOctets, 0 },
1528 { &entry->cAttribute, CRYPT_AsnEncodePKCSAttributes, 0 },
1530 BOOL ret;
1532 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1533 sizeof(items) / sizeof(items[0]), 0, NULL, pbEncoded, pcbEncoded);
1534 return ret;
1537 struct CTLEntries
1539 DWORD cEntry;
1540 CTL_ENTRY *rgEntry;
1543 static BOOL WINAPI CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType,
1544 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1545 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1547 BOOL ret;
1548 DWORD bytesNeeded, dataLen, lenBytes, i;
1549 const struct CTLEntries *entries = pvStructInfo;
1551 ret = TRUE;
1552 for (i = 0, dataLen = 0; ret && i < entries->cEntry; i++)
1554 DWORD size;
1556 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i], NULL, &size);
1557 if (ret)
1558 dataLen += size;
1560 if (ret)
1562 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1563 bytesNeeded = 1 + lenBytes + dataLen;
1564 if (!pbEncoded)
1565 *pcbEncoded = bytesNeeded;
1566 else
1568 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1569 pbEncoded, pcbEncoded, bytesNeeded)))
1571 BYTE *out;
1573 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1574 pbEncoded = *(BYTE **)pbEncoded;
1575 out = pbEncoded;
1576 *out++ = ASN_SEQUENCEOF;
1577 CRYPT_EncodeLen(dataLen, out, &lenBytes);
1578 out += lenBytes;
1579 for (i = 0; ret && i < entries->cEntry; i++)
1581 DWORD size = dataLen;
1583 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i],
1584 out, &size);
1585 out += size;
1586 dataLen -= size;
1588 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1589 CRYPT_FreeSpace(pEncodePara, pbEncoded);
1593 return ret;
1596 static BOOL WINAPI CRYPT_AsnEncodeCTL(DWORD dwCertEncodingType,
1597 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1598 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1600 BOOL ret = FALSE;
1602 __TRY
1604 const CTL_INFO *info = pvStructInfo;
1605 struct AsnEncodeSequenceItem items[9] = {
1606 { &info->dwVersion, CRYPT_AsnEncodeCTLVersion, 0 },
1607 { &info->SubjectUsage, CRYPT_AsnEncodeEnhancedKeyUsage, 0 },
1609 struct AsnConstructedItem constructed = { 0 };
1610 DWORD cItem = 2;
1612 if (info->ListIdentifier.cbData)
1614 items[cItem].pvStructInfo = &info->ListIdentifier;
1615 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
1616 cItem++;
1618 if (info->SequenceNumber.cbData)
1620 items[cItem].pvStructInfo = &info->SequenceNumber;
1621 items[cItem].encodeFunc = CRYPT_AsnEncodeInteger;
1622 cItem++;
1624 items[cItem].pvStructInfo = &info->ThisUpdate;
1625 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1626 cItem++;
1627 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
1629 items[cItem].pvStructInfo = &info->NextUpdate;
1630 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1631 cItem++;
1633 items[cItem].pvStructInfo = &info->SubjectAlgorithm;
1634 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLSubjectAlgorithm;
1635 cItem++;
1636 if (info->cCTLEntry)
1638 items[cItem].pvStructInfo = &info->cCTLEntry;
1639 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLEntries;
1640 cItem++;
1642 if (info->cExtension)
1644 constructed.tag = 0;
1645 constructed.pvStructInfo = &info->cExtension;
1646 constructed.encodeFunc = CRYPT_AsnEncodeExtensions;
1647 items[cItem].pvStructInfo = &constructed;
1648 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1649 cItem++;
1651 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1652 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1654 __EXCEPT_PAGE_FAULT
1656 SetLastError(STATUS_ACCESS_VIOLATION);
1658 __ENDTRY
1659 return ret;
1662 static BOOL CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType,
1663 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1664 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1666 BOOL ret = FALSE;
1668 __TRY
1670 const CRYPT_SMIME_CAPABILITY *capability = pvStructInfo;
1672 if (!capability->pszObjId)
1673 SetLastError(E_INVALIDARG);
1674 else
1676 struct AsnEncodeSequenceItem items[] = {
1677 { capability->pszObjId, CRYPT_AsnEncodeOid, 0 },
1678 { &capability->Parameters, CRYPT_CopyEncodedBlob, 0 },
1681 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1682 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1683 pcbEncoded);
1686 __EXCEPT_PAGE_FAULT
1688 SetLastError(STATUS_ACCESS_VIOLATION);
1690 __ENDTRY
1691 return ret;
1694 static BOOL WINAPI CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType,
1695 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1696 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1698 BOOL ret = FALSE;
1700 __TRY
1702 DWORD bytesNeeded, dataLen, lenBytes, i;
1703 const CRYPT_SMIME_CAPABILITIES *capabilities = pvStructInfo;
1705 ret = TRUE;
1706 for (i = 0, dataLen = 0; ret && i < capabilities->cCapability; i++)
1708 DWORD size;
1710 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType, NULL,
1711 &capabilities->rgCapability[i], 0, NULL, NULL, &size);
1712 if (ret)
1713 dataLen += size;
1715 if (ret)
1717 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1718 bytesNeeded = 1 + lenBytes + dataLen;
1719 if (!pbEncoded)
1720 *pcbEncoded = bytesNeeded;
1721 else
1723 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1724 pbEncoded, pcbEncoded, bytesNeeded)))
1726 BYTE *out;
1728 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1729 pbEncoded = *(BYTE **)pbEncoded;
1730 out = pbEncoded;
1731 *out++ = ASN_SEQUENCEOF;
1732 CRYPT_EncodeLen(dataLen, out, &lenBytes);
1733 out += lenBytes;
1734 for (i = 0; i < capabilities->cCapability; i++)
1736 DWORD size = dataLen;
1738 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType,
1739 NULL, &capabilities->rgCapability[i], 0, NULL,
1740 out, &size);
1741 out += size;
1742 dataLen -= size;
1744 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1745 CRYPT_FreeSpace(pEncodePara, pbEncoded);
1750 __EXCEPT_PAGE_FAULT
1752 SetLastError(STATUS_ACCESS_VIOLATION);
1754 __ENDTRY
1755 return ret;
1758 static BOOL WINAPI CRYPT_AsnEncodeNoticeNumbers(DWORD dwCertEncodingType,
1759 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1760 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1762 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
1763 DWORD bytesNeeded, dataLen, lenBytes, i;
1764 BOOL ret = TRUE;
1766 for (i = 0, dataLen = 0; ret && i < noticeRef->cNoticeNumbers; i++)
1768 DWORD size;
1770 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
1771 &noticeRef->rgNoticeNumbers[i], 0, NULL, NULL, &size);
1772 if (ret)
1773 dataLen += size;
1775 if (ret)
1777 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1778 bytesNeeded = 1 + lenBytes + dataLen;
1779 if (!pbEncoded)
1780 *pcbEncoded = bytesNeeded;
1781 else
1783 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1784 pcbEncoded, bytesNeeded)))
1786 BYTE *out;
1788 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1789 pbEncoded = *(BYTE **)pbEncoded;
1790 out = pbEncoded;
1791 *out++ = ASN_SEQUENCE;
1792 CRYPT_EncodeLen(dataLen, out, &lenBytes);
1793 out += lenBytes;
1794 for (i = 0; i < noticeRef->cNoticeNumbers; i++)
1796 DWORD size = dataLen;
1798 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
1799 &noticeRef->rgNoticeNumbers[i], 0, NULL, out, &size);
1800 out += size;
1801 dataLen -= size;
1803 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1804 CRYPT_FreeSpace(pEncodePara, pbEncoded);
1808 return ret;
1811 static BOOL WINAPI CRYPT_AsnEncodeNoticeReference(DWORD dwCertEncodingType,
1812 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1813 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1815 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
1816 BOOL ret;
1817 CERT_NAME_VALUE orgValue = { CERT_RDN_IA5_STRING,
1818 { 0, (LPBYTE)noticeRef->pszOrganization } };
1819 struct AsnEncodeSequenceItem items[] = {
1820 { &orgValue, CRYPT_AsnEncodeNameValue, 0 },
1821 { noticeRef, CRYPT_AsnEncodeNoticeNumbers, 0 },
1824 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1825 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1826 pcbEncoded);
1827 return ret;
1830 static BOOL WINAPI CRYPT_AsnEncodePolicyQualifierUserNotice(
1831 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1832 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1833 DWORD *pcbEncoded)
1835 BOOL ret = FALSE;
1837 __TRY
1839 const CERT_POLICY_QUALIFIER_USER_NOTICE *notice = pvStructInfo;
1840 struct AsnEncodeSequenceItem items[2];
1841 CERT_NAME_VALUE displayTextValue;
1842 DWORD cItem = 0;
1844 if (notice->pNoticeReference)
1846 items[cItem].encodeFunc = CRYPT_AsnEncodeNoticeReference;
1847 items[cItem].pvStructInfo = notice->pNoticeReference;
1848 cItem++;
1850 if (notice->pszDisplayText)
1852 displayTextValue.dwValueType = CERT_RDN_BMP_STRING;
1853 displayTextValue.Value.cbData = 0;
1854 displayTextValue.Value.pbData = (LPBYTE)notice->pszDisplayText;
1855 items[cItem].encodeFunc = CRYPT_AsnEncodeNameValue;
1856 items[cItem].pvStructInfo = &displayTextValue;
1857 cItem++;
1859 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1860 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1862 __EXCEPT_PAGE_FAULT
1864 SetLastError(STATUS_ACCESS_VIOLATION);
1866 __ENDTRY
1867 return ret;
1870 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1871 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1872 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1874 BOOL ret = FALSE;
1876 __TRY
1878 const CRYPT_ATTRIBUTE *attr = pvStructInfo;
1880 if (!attr->pszObjId)
1881 SetLastError(E_INVALIDARG);
1882 else
1884 struct AsnEncodeSequenceItem items[2] = {
1885 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1886 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1889 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1890 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1891 pcbEncoded);
1894 __EXCEPT_PAGE_FAULT
1896 SetLastError(STATUS_ACCESS_VIOLATION);
1898 __ENDTRY
1899 return ret;
1902 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1903 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1904 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1906 BOOL ret = FALSE;
1908 __TRY
1910 const CRYPT_ATTRIBUTES *attributes = pvStructInfo;
1911 struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
1912 sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
1914 ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
1915 &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1917 __EXCEPT_PAGE_FAULT
1919 SetLastError(STATUS_ACCESS_VIOLATION);
1921 __ENDTRY
1922 return ret;
1925 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1926 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
1927 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1928 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1929 DWORD *pcbEncoded)
1931 const CRYPT_CONTENT_INFO *info = pvStructInfo;
1932 struct AsnEncodeSequenceItem items[2] = {
1933 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1934 { NULL, NULL, 0 },
1936 struct AsnConstructedItem constructed = { 0 };
1937 DWORD cItem = 1;
1939 if (info->Content.cbData)
1941 constructed.tag = 0;
1942 constructed.pvStructInfo = &info->Content;
1943 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1944 items[cItem].pvStructInfo = &constructed;
1945 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1946 cItem++;
1948 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1949 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1952 BOOL CRYPT_AsnEncodePKCSDigestedData(const CRYPT_DIGESTED_DATA *digestedData,
1953 void *pvData, DWORD *pcbData)
1955 struct AsnEncodeSequenceItem items[] = {
1956 { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1957 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
1958 0 },
1959 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1960 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1963 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1964 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
1967 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1968 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1969 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1971 BOOL ret = FALSE;
1973 __TRY
1975 const CRYPT_CONTENT_INFO *info = pvStructInfo;
1977 if (!info->pszObjId)
1978 SetLastError(E_INVALIDARG);
1979 else
1980 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
1981 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1982 pcbEncoded);
1984 __EXCEPT_PAGE_FAULT
1986 SetLastError(STATUS_ACCESS_VIOLATION);
1988 __ENDTRY
1989 return ret;
1992 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1993 BYTE tag, DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
1994 DWORD *pcbEncoded)
1996 BOOL ret = TRUE;
1997 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1998 DWORD bytesNeeded, lenBytes, encodedLen;
2000 if (value->Value.cbData)
2001 encodedLen = value->Value.cbData / sizeof(WCHAR);
2002 else if (str)
2003 encodedLen = strlenW(str);
2004 else
2005 encodedLen = 0;
2006 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2007 bytesNeeded = 1 + lenBytes + encodedLen;
2008 if (!pbEncoded)
2009 *pcbEncoded = bytesNeeded;
2010 else
2012 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2013 pbEncoded, pcbEncoded, bytesNeeded)))
2015 DWORD i;
2017 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2018 pbEncoded = *(BYTE **)pbEncoded;
2019 *pbEncoded++ = tag;
2020 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
2021 pbEncoded += lenBytes;
2022 for (i = 0; i < encodedLen; i++)
2023 *pbEncoded++ = (BYTE)str[i];
2026 return ret;
2029 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
2030 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2031 DWORD *pcbEncoded)
2033 BOOL ret = TRUE;
2034 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2035 DWORD bytesNeeded, lenBytes, encodedLen;
2037 if (value->Value.cbData)
2038 encodedLen = value->Value.cbData / sizeof(WCHAR);
2039 else if (str)
2040 encodedLen = strlenW(str);
2041 else
2042 encodedLen = 0;
2043 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2044 bytesNeeded = 1 + lenBytes + encodedLen;
2045 if (!pbEncoded)
2046 *pcbEncoded = bytesNeeded;
2047 else
2049 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2050 pbEncoded, pcbEncoded, bytesNeeded)))
2052 DWORD i;
2053 BYTE *ptr;
2055 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2056 ptr = *(BYTE **)pbEncoded;
2057 else
2058 ptr = pbEncoded;
2059 *ptr++ = ASN_NUMERICSTRING;
2060 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2061 ptr += lenBytes;
2062 for (i = 0; ret && i < encodedLen; i++)
2064 if (isdigitW(str[i]))
2065 *ptr++ = (BYTE)str[i];
2066 else
2068 *pcbEncoded = i;
2069 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
2070 ret = FALSE;
2073 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2074 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2077 return ret;
2080 static inline int isprintableW(WCHAR wc)
2082 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
2083 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
2084 wc == '/' || wc == ':' || wc == '=' || wc == '?';
2087 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
2088 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2089 DWORD *pcbEncoded)
2091 BOOL ret = TRUE;
2092 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2093 DWORD bytesNeeded, lenBytes, encodedLen;
2095 if (value->Value.cbData)
2096 encodedLen = value->Value.cbData / sizeof(WCHAR);
2097 else if (str)
2098 encodedLen = strlenW(str);
2099 else
2100 encodedLen = 0;
2101 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2102 bytesNeeded = 1 + lenBytes + encodedLen;
2103 if (!pbEncoded)
2104 *pcbEncoded = bytesNeeded;
2105 else
2107 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2108 pbEncoded, pcbEncoded, bytesNeeded)))
2110 DWORD i;
2111 BYTE *ptr;
2113 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2114 ptr = *(BYTE **)pbEncoded;
2115 else
2116 ptr = pbEncoded;
2117 *ptr++ = ASN_PRINTABLESTRING;
2118 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2119 ptr += lenBytes;
2120 for (i = 0; ret && i < encodedLen; i++)
2122 if (isprintableW(str[i]))
2123 *ptr++ = (BYTE)str[i];
2124 else
2126 *pcbEncoded = i;
2127 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
2128 ret = FALSE;
2131 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2132 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2135 return ret;
2138 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
2139 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2140 DWORD *pcbEncoded)
2142 BOOL ret = TRUE;
2143 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2144 DWORD bytesNeeded, lenBytes, encodedLen;
2146 if (value->Value.cbData)
2147 encodedLen = value->Value.cbData / sizeof(WCHAR);
2148 else if (str)
2149 encodedLen = strlenW(str);
2150 else
2151 encodedLen = 0;
2152 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2153 bytesNeeded = 1 + lenBytes + encodedLen;
2154 if (!pbEncoded)
2155 *pcbEncoded = bytesNeeded;
2156 else
2158 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2159 pbEncoded, pcbEncoded, bytesNeeded)))
2161 DWORD i;
2162 BYTE *ptr;
2164 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2165 ptr = *(BYTE **)pbEncoded;
2166 else
2167 ptr = pbEncoded;
2168 *ptr++ = ASN_IA5STRING;
2169 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2170 ptr += lenBytes;
2171 for (i = 0; ret && i < encodedLen; i++)
2173 if (str[i] <= 0x7f)
2174 *ptr++ = (BYTE)str[i];
2175 else
2177 *pcbEncoded = i;
2178 SetLastError(CRYPT_E_INVALID_IA5_STRING);
2179 ret = FALSE;
2182 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2183 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2186 return ret;
2189 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
2190 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2191 DWORD *pcbEncoded)
2193 BOOL ret = TRUE;
2194 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2195 DWORD bytesNeeded, lenBytes, strLen;
2197 /* FIXME: doesn't handle composite characters */
2198 if (value->Value.cbData)
2199 strLen = value->Value.cbData / sizeof(WCHAR);
2200 else if (str)
2201 strLen = strlenW(str);
2202 else
2203 strLen = 0;
2204 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
2205 bytesNeeded = 1 + lenBytes + strLen * 4;
2206 if (!pbEncoded)
2207 *pcbEncoded = bytesNeeded;
2208 else
2210 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2211 pbEncoded, pcbEncoded, bytesNeeded)))
2213 DWORD i;
2215 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2216 pbEncoded = *(BYTE **)pbEncoded;
2217 *pbEncoded++ = ASN_UNIVERSALSTRING;
2218 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
2219 pbEncoded += lenBytes;
2220 for (i = 0; i < strLen; i++)
2222 *pbEncoded++ = 0;
2223 *pbEncoded++ = 0;
2224 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
2225 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
2229 return ret;
2232 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
2233 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2234 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2236 BOOL ret = FALSE;
2238 __TRY
2240 const CERT_NAME_VALUE *value = pvStructInfo;
2242 switch (value->dwValueType)
2244 case CERT_RDN_ANY_TYPE:
2245 case CERT_RDN_ENCODED_BLOB:
2246 case CERT_RDN_OCTET_STRING:
2247 SetLastError(CRYPT_E_NOT_CHAR_STRING);
2248 break;
2249 case CERT_RDN_NUMERIC_STRING:
2250 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
2251 pbEncoded, pcbEncoded);
2252 break;
2253 case CERT_RDN_PRINTABLE_STRING:
2254 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
2255 pbEncoded, pcbEncoded);
2256 break;
2257 case CERT_RDN_TELETEX_STRING:
2258 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
2259 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2260 break;
2261 case CERT_RDN_VIDEOTEX_STRING:
2262 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
2263 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2264 break;
2265 case CERT_RDN_IA5_STRING:
2266 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
2267 pbEncoded, pcbEncoded);
2268 break;
2269 case CERT_RDN_GRAPHIC_STRING:
2270 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
2271 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2272 break;
2273 case CERT_RDN_VISIBLE_STRING:
2274 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
2275 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2276 break;
2277 case CERT_RDN_GENERAL_STRING:
2278 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
2279 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2280 break;
2281 case CERT_RDN_UNIVERSAL_STRING:
2282 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
2283 pbEncoded, pcbEncoded);
2284 break;
2285 case CERT_RDN_BMP_STRING:
2286 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
2287 pbEncoded, pcbEncoded);
2288 break;
2289 case CERT_RDN_UTF8_STRING:
2290 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
2291 pbEncoded, pcbEncoded);
2292 break;
2293 default:
2294 SetLastError(CRYPT_E_ASN1_CHOICE);
2297 __EXCEPT_PAGE_FAULT
2299 SetLastError(STATUS_ACCESS_VIOLATION);
2301 __ENDTRY
2302 return ret;
2305 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
2306 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2307 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2309 BOOL ret;
2311 __TRY
2313 const CERT_NAME_INFO *info = pvStructInfo;
2314 DWORD bytesNeeded = 0, lenBytes, size, i;
2316 TRACE("encoding name with %d RDNs\n", info->cRDN);
2317 ret = TRUE;
2318 for (i = 0; ret && i < info->cRDN; i++)
2320 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
2321 CRYPT_AsnEncodeNameValue, NULL, &size);
2322 if (ret)
2323 bytesNeeded += size;
2325 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2326 bytesNeeded += 1 + lenBytes;
2327 if (ret)
2329 if (!pbEncoded)
2330 *pcbEncoded = bytesNeeded;
2331 else
2333 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2334 pbEncoded, pcbEncoded, bytesNeeded)))
2336 BYTE *out;
2338 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2339 pbEncoded = *(BYTE **)pbEncoded;
2340 out = pbEncoded;
2341 *out++ = ASN_SEQUENCEOF;
2342 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
2343 out += lenBytes;
2344 for (i = 0; ret && i < info->cRDN; i++)
2346 size = bytesNeeded;
2347 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
2348 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, out, &size);
2349 if (ret)
2351 out += size;
2352 bytesNeeded -= size;
2355 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2356 CRYPT_FreeSpace(pEncodePara, pbEncoded);
2361 __EXCEPT_PAGE_FAULT
2363 SetLastError(STATUS_ACCESS_VIOLATION);
2364 ret = FALSE;
2366 __ENDTRY
2367 return ret;
2370 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
2371 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2372 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2374 BOOL val = *(const BOOL *)pvStructInfo, ret;
2376 TRACE("%d\n", val);
2378 if (!pbEncoded)
2380 *pcbEncoded = 3;
2381 ret = TRUE;
2383 else if (*pcbEncoded < 3)
2385 *pcbEncoded = 3;
2386 SetLastError(ERROR_MORE_DATA);
2387 ret = FALSE;
2389 else
2391 *pcbEncoded = 3;
2392 *pbEncoded++ = ASN_BOOL;
2393 *pbEncoded++ = 1;
2394 *pbEncoded++ = val ? 0xff : 0;
2395 ret = TRUE;
2397 TRACE("returning %d (%08x)\n", ret, GetLastError());
2398 return ret;
2401 static BOOL WINAPI CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType,
2402 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2403 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2405 const CERT_ALT_NAME_ENTRY *entry = pvStructInfo;
2406 BOOL ret;
2407 DWORD dataLen;
2408 BYTE tag;
2410 ret = TRUE;
2411 switch (entry->dwAltNameChoice)
2413 case CERT_ALT_NAME_RFC822_NAME:
2414 case CERT_ALT_NAME_DNS_NAME:
2415 case CERT_ALT_NAME_URL:
2416 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2417 if (entry->u.pwszURL)
2419 DWORD i;
2421 /* Not + 1: don't encode the NULL-terminator */
2422 dataLen = lstrlenW(entry->u.pwszURL);
2423 for (i = 0; ret && i < dataLen; i++)
2425 if (entry->u.pwszURL[i] > 0x7f)
2427 SetLastError(CRYPT_E_INVALID_IA5_STRING);
2428 ret = FALSE;
2429 *pcbEncoded = i;
2433 else
2434 dataLen = 0;
2435 break;
2436 case CERT_ALT_NAME_DIRECTORY_NAME:
2437 tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1);
2438 dataLen = entry->u.DirectoryName.cbData;
2439 break;
2440 case CERT_ALT_NAME_IP_ADDRESS:
2441 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2442 dataLen = entry->u.IPAddress.cbData;
2443 break;
2444 case CERT_ALT_NAME_REGISTERED_ID:
2446 struct AsnEncodeTagSwappedItem swapped =
2447 { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID,
2448 CRYPT_AsnEncodeOid };
2450 return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded,
2451 pcbEncoded);
2453 case CERT_ALT_NAME_OTHER_NAME:
2454 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
2455 return FALSE;
2456 default:
2457 SetLastError(E_INVALIDARG);
2458 return FALSE;
2460 if (ret)
2462 DWORD bytesNeeded, lenBytes;
2464 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2465 bytesNeeded = 1 + dataLen + lenBytes;
2466 if (!pbEncoded)
2467 *pcbEncoded = bytesNeeded;
2468 else if (*pcbEncoded < bytesNeeded)
2470 SetLastError(ERROR_MORE_DATA);
2471 *pcbEncoded = bytesNeeded;
2472 ret = FALSE;
2474 else
2476 *pbEncoded++ = tag;
2477 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2478 pbEncoded += lenBytes;
2479 switch (entry->dwAltNameChoice)
2481 case CERT_ALT_NAME_RFC822_NAME:
2482 case CERT_ALT_NAME_DNS_NAME:
2483 case CERT_ALT_NAME_URL:
2485 DWORD i;
2487 for (i = 0; i < dataLen; i++)
2488 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
2489 break;
2491 case CERT_ALT_NAME_DIRECTORY_NAME:
2492 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen);
2493 break;
2494 case CERT_ALT_NAME_IP_ADDRESS:
2495 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
2496 break;
2498 if (ret)
2499 *pcbEncoded = bytesNeeded;
2502 TRACE("returning %d (%08x)\n", ret, GetLastError());
2503 return ret;
2506 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
2507 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2508 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2510 BOOL ret;
2512 __TRY
2514 const CERT_AUTHORITY_KEY_ID_INFO *info = pvStructInfo;
2515 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2516 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2517 struct AsnConstructedItem constructed = { 0 };
2518 DWORD cItem = 0, cSwapped = 0;
2520 if (info->KeyId.cbData)
2522 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2523 swapped[cSwapped].pvStructInfo = &info->KeyId;
2524 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
2525 items[cItem].pvStructInfo = &swapped[cSwapped];
2526 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2527 cSwapped++;
2528 cItem++;
2530 if (info->CertIssuer.cbData)
2532 constructed.tag = 1;
2533 constructed.pvStructInfo = &info->CertIssuer;
2534 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2535 items[cItem].pvStructInfo = &constructed;
2536 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2537 cItem++;
2539 if (info->CertSerialNumber.cbData)
2541 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2542 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2543 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2544 items[cItem].pvStructInfo = &swapped[cSwapped];
2545 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2546 cSwapped++;
2547 cItem++;
2549 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2550 pEncodePara, pbEncoded, pcbEncoded);
2552 __EXCEPT_PAGE_FAULT
2554 SetLastError(STATUS_ACCESS_VIOLATION);
2555 ret = FALSE;
2557 __ENDTRY
2558 return ret;
2561 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2562 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2563 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2565 BOOL ret;
2567 __TRY
2569 const CERT_ALT_NAME_INFO *info = pvStructInfo;
2570 DWORD bytesNeeded, dataLen, lenBytes, i;
2572 ret = TRUE;
2573 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2574 * can't encode an erroneous entry index if it's bigger than this.
2576 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2578 DWORD len;
2580 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, NULL,
2581 &info->rgAltEntry[i], 0, NULL, NULL, &len);
2582 if (ret)
2583 dataLen += len;
2584 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2586 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2587 * the bad character, now set the index of the bad
2588 * entry
2590 *pcbEncoded = (BYTE)i <<
2591 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2594 if (ret)
2596 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2597 bytesNeeded = 1 + lenBytes + dataLen;
2598 if (!pbEncoded)
2600 *pcbEncoded = bytesNeeded;
2601 ret = TRUE;
2603 else
2605 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2606 pbEncoded, pcbEncoded, bytesNeeded)))
2608 BYTE *out;
2610 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2611 pbEncoded = *(BYTE **)pbEncoded;
2612 out = pbEncoded;
2613 *out++ = ASN_SEQUENCEOF;
2614 CRYPT_EncodeLen(dataLen, out, &lenBytes);
2615 out += lenBytes;
2616 for (i = 0; ret && i < info->cAltEntry; i++)
2618 DWORD len = dataLen;
2620 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType,
2621 NULL, &info->rgAltEntry[i], 0, NULL, out, &len);
2622 if (ret)
2624 out += len;
2625 dataLen -= len;
2628 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2629 CRYPT_FreeSpace(pEncodePara, pbEncoded);
2634 __EXCEPT_PAGE_FAULT
2636 SetLastError(STATUS_ACCESS_VIOLATION);
2637 ret = FALSE;
2639 __ENDTRY
2640 return ret;
2643 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2644 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2645 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2647 BOOL ret;
2649 __TRY
2651 const CERT_AUTHORITY_KEY_ID2_INFO *info = pvStructInfo;
2652 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2653 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2654 DWORD cItem = 0, cSwapped = 0;
2656 if (info->KeyId.cbData)
2658 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2659 swapped[cSwapped].pvStructInfo = &info->KeyId;
2660 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
2661 items[cItem].pvStructInfo = &swapped[cSwapped];
2662 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2663 cSwapped++;
2664 cItem++;
2666 if (info->AuthorityCertIssuer.cAltEntry)
2668 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2669 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2670 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2671 items[cItem].pvStructInfo = &swapped[cSwapped];
2672 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2673 cSwapped++;
2674 cItem++;
2676 if (info->AuthorityCertSerialNumber.cbData)
2678 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2679 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2680 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2681 items[cItem].pvStructInfo = &swapped[cSwapped];
2682 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2683 cSwapped++;
2684 cItem++;
2686 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2687 pEncodePara, pbEncoded, pcbEncoded);
2689 __EXCEPT_PAGE_FAULT
2691 SetLastError(STATUS_ACCESS_VIOLATION);
2692 ret = FALSE;
2694 __ENDTRY
2695 return ret;
2698 static BOOL CRYPT_AsnEncodeAccessDescription(
2699 const CERT_ACCESS_DESCRIPTION *descr, BYTE *pbEncoded, DWORD *pcbEncoded)
2701 struct AsnEncodeSequenceItem items[] = {
2702 { descr->pszAccessMethod, CRYPT_AsnEncodeOid, 0 },
2703 { &descr->AccessLocation, CRYPT_AsnEncodeAltNameEntry, 0 },
2706 if (!descr->pszAccessMethod)
2708 SetLastError(E_INVALIDARG);
2709 return FALSE;
2711 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
2712 sizeof(items) / sizeof(items[0]), 0, NULL, pbEncoded, pcbEncoded);
2715 static BOOL WINAPI CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType,
2716 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2717 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2719 BOOL ret;
2721 __TRY
2723 DWORD bytesNeeded, dataLen, lenBytes, i;
2724 const CERT_AUTHORITY_INFO_ACCESS *info = pvStructInfo;
2726 ret = TRUE;
2727 for (i = 0, dataLen = 0; ret && i < info->cAccDescr; i++)
2729 DWORD size;
2731 ret = CRYPT_AsnEncodeAccessDescription(&info->rgAccDescr[i], NULL,
2732 &size);
2733 if (ret)
2734 dataLen += size;
2736 if (ret)
2738 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2739 bytesNeeded = 1 + lenBytes + dataLen;
2740 if (!pbEncoded)
2741 *pcbEncoded = bytesNeeded;
2742 else
2744 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2745 pbEncoded, pcbEncoded, bytesNeeded)))
2747 BYTE *out;
2749 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2750 pbEncoded = *(BYTE **)pbEncoded;
2751 out = pbEncoded;
2752 *out++ = ASN_SEQUENCEOF;
2753 CRYPT_EncodeLen(dataLen, out, &lenBytes);
2754 out += lenBytes;
2755 for (i = 0; i < info->cAccDescr; i++)
2757 DWORD size = dataLen;
2759 ret = CRYPT_AsnEncodeAccessDescription(
2760 &info->rgAccDescr[i], out, &size);
2761 out += size;
2762 dataLen -= size;
2764 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2765 CRYPT_FreeSpace(pEncodePara, pbEncoded);
2770 __EXCEPT_PAGE_FAULT
2772 SetLastError(STATUS_ACCESS_VIOLATION);
2773 ret = FALSE;
2775 __ENDTRY
2776 return ret;
2779 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2780 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2781 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2783 BOOL ret;
2785 __TRY
2787 const CERT_BASIC_CONSTRAINTS_INFO *info = pvStructInfo;
2788 struct AsnEncodeSequenceItem items[3] = {
2789 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2790 { 0 }
2792 DWORD cItem = 1;
2794 if (info->fPathLenConstraint)
2796 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2797 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2798 cItem++;
2800 if (info->cSubtreesConstraint)
2802 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2803 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2804 cItem++;
2806 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2807 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2809 __EXCEPT_PAGE_FAULT
2811 SetLastError(STATUS_ACCESS_VIOLATION);
2812 ret = FALSE;
2814 __ENDTRY
2815 return ret;
2818 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2819 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2820 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2822 BOOL ret;
2824 __TRY
2826 const CERT_BASIC_CONSTRAINTS2_INFO *info = pvStructInfo;
2827 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2828 DWORD cItem = 0;
2830 if (info->fCA)
2832 items[cItem].pvStructInfo = &info->fCA;
2833 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2834 cItem++;
2836 if (info->fPathLenConstraint)
2838 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2839 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2840 cItem++;
2842 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2843 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2845 __EXCEPT_PAGE_FAULT
2847 SetLastError(STATUS_ACCESS_VIOLATION);
2848 ret = FALSE;
2850 __ENDTRY
2851 return ret;
2854 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType,
2855 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2856 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2858 const CERT_POLICY_INFO *info = pvStructInfo;
2859 BOOL ret;
2861 if (!info->cPolicyQualifier)
2863 *pcbEncoded = 0;
2864 ret = TRUE;
2866 else
2868 struct AsnEncodeSequenceItem items[2] = {
2869 { NULL, CRYPT_AsnEncodeOid, 0 },
2870 { NULL, CRYPT_CopyEncodedBlob, 0 },
2872 DWORD bytesNeeded = 0, lenBytes, size, i;
2874 ret = TRUE;
2875 for (i = 0; ret && i < info->cPolicyQualifier; i++)
2877 items[0].pvStructInfo =
2878 info->rgPolicyQualifier[i].pszPolicyQualifierId;
2879 items[1].pvStructInfo = &info->rgPolicyQualifier[i].Qualifier;
2880 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2881 sizeof(items) / sizeof(items[0]),
2882 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
2883 if (ret)
2884 bytesNeeded += size;
2886 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2887 bytesNeeded += 1 + lenBytes;
2888 if (ret)
2890 if (!pbEncoded)
2891 *pcbEncoded = bytesNeeded;
2892 else
2894 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2895 pbEncoded, pcbEncoded, bytesNeeded)))
2897 BYTE *out;
2899 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2900 pbEncoded = *(BYTE **)pbEncoded;
2901 out = pbEncoded;
2902 *out++ = ASN_SEQUENCEOF;
2903 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
2904 out += lenBytes;
2905 for (i = 0; ret && i < info->cPolicyQualifier; i++)
2907 items[0].pvStructInfo =
2908 info->rgPolicyQualifier[i].pszPolicyQualifierId;
2909 items[1].pvStructInfo =
2910 &info->rgPolicyQualifier[i].Qualifier;
2911 size = bytesNeeded;
2912 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2913 sizeof(items) / sizeof(items[0]),
2914 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, out, &size);
2915 if (ret)
2917 out += size;
2918 bytesNeeded -= size;
2921 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2922 CRYPT_FreeSpace(pEncodePara, pbEncoded);
2927 return ret;
2930 static BOOL CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType,
2931 const CERT_POLICY_INFO *info, DWORD dwFlags, BYTE *pbEncoded,
2932 DWORD *pcbEncoded)
2934 struct AsnEncodeSequenceItem items[2] = {
2935 { info->pszPolicyIdentifier, CRYPT_AsnEncodeOid, 0 },
2936 { info, CRYPT_AsnEncodeCertPolicyQualifiers, 0 },
2938 BOOL ret;
2940 if (!info->pszPolicyIdentifier)
2942 SetLastError(E_INVALIDARG);
2943 return FALSE;
2945 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2946 sizeof(items) / sizeof(items[0]), dwFlags, NULL, pbEncoded, pcbEncoded);
2947 return ret;
2950 static BOOL WINAPI CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType,
2951 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2952 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2954 BOOL ret = FALSE;
2956 __TRY
2958 const CERT_POLICIES_INFO *info = pvStructInfo;
2959 DWORD bytesNeeded = 0, lenBytes, size, i;
2961 ret = TRUE;
2962 for (i = 0; ret && i < info->cPolicyInfo; i++)
2964 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
2965 &info->rgPolicyInfo[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
2966 &size);
2967 if (ret)
2968 bytesNeeded += size;
2970 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2971 bytesNeeded += 1 + lenBytes;
2972 if (ret)
2974 if (!pbEncoded)
2975 *pcbEncoded = bytesNeeded;
2976 else
2978 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2979 pbEncoded, pcbEncoded, bytesNeeded)))
2981 BYTE *out;
2983 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2984 pbEncoded = *(BYTE **)pbEncoded;
2985 out = pbEncoded;
2986 *out++ = ASN_SEQUENCEOF;
2987 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
2988 out += lenBytes;
2989 for (i = 0; ret && i < info->cPolicyInfo; i++)
2991 size = bytesNeeded;
2992 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
2993 &info->rgPolicyInfo[i],
2994 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, out, &size);
2995 if (ret)
2997 out += size;
2998 bytesNeeded -= size;
3001 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
3002 CRYPT_FreeSpace(pEncodePara, pbEncoded);
3007 __EXCEPT_PAGE_FAULT
3009 SetLastError(STATUS_ACCESS_VIOLATION);
3011 __ENDTRY
3012 return ret;
3015 static BOOL CRYPT_AsnEncodeCertPolicyMapping(DWORD dwCertEncodingType,
3016 const CERT_POLICY_MAPPING *mapping, DWORD dwFlags, BYTE *pbEncoded,
3017 DWORD *pcbEncoded)
3019 struct AsnEncodeSequenceItem items[] = {
3020 { mapping->pszIssuerDomainPolicy, CRYPT_AsnEncodeOid, 0 },
3021 { mapping->pszSubjectDomainPolicy, CRYPT_AsnEncodeOid, 0 },
3024 if (!mapping->pszIssuerDomainPolicy || !mapping->pszSubjectDomainPolicy)
3026 SetLastError(E_INVALIDARG);
3027 return FALSE;
3029 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3030 sizeof(items) / sizeof(items[0]), dwFlags, NULL, pbEncoded, pcbEncoded);
3033 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyMappings(DWORD dwCertEncodingType,
3034 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3035 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3037 BOOL ret = FALSE;
3039 __TRY
3041 const CERT_POLICY_MAPPINGS_INFO *info = pvStructInfo;
3042 DWORD bytesNeeded = 0, lenBytes, size, i;
3044 ret = TRUE;
3045 for (i = 0; ret && i < info->cPolicyMapping; i++)
3047 ret = CRYPT_AsnEncodeCertPolicyMapping(dwCertEncodingType,
3048 &info->rgPolicyMapping[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
3049 NULL, &size);
3050 if (ret)
3051 bytesNeeded += size;
3053 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3054 bytesNeeded += 1 + lenBytes;
3055 if (ret)
3057 if (!pbEncoded)
3058 *pcbEncoded = bytesNeeded;
3059 else
3061 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3062 pbEncoded, pcbEncoded, bytesNeeded)))
3064 BYTE *out;
3066 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3067 pbEncoded = *(BYTE **)pbEncoded;
3068 out = pbEncoded;
3069 *out++ = ASN_SEQUENCEOF;
3070 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
3071 out += lenBytes;
3072 for (i = 0; ret && i < info->cPolicyMapping; i++)
3074 size = bytesNeeded;
3075 ret = CRYPT_AsnEncodeCertPolicyMapping(
3076 dwCertEncodingType, &info->rgPolicyMapping[i],
3077 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, out, &size);
3078 if (ret)
3080 out += size;
3081 bytesNeeded -= size;
3084 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
3085 CRYPT_FreeSpace(pEncodePara, pbEncoded);
3090 __EXCEPT_PAGE_FAULT
3092 SetLastError(STATUS_ACCESS_VIOLATION);
3094 __ENDTRY
3095 return ret;
3098 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyConstraints(
3099 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3100 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3101 DWORD *pcbEncoded)
3103 BOOL ret = FALSE;
3105 __TRY
3107 const CERT_POLICY_CONSTRAINTS_INFO *info = pvStructInfo;
3108 struct AsnEncodeSequenceItem items[2];
3109 struct AsnEncodeTagSwappedItem swapped[2];
3110 DWORD cItem = 0, cSwapped = 0;
3112 if (info->fRequireExplicitPolicy)
3114 swapped[cSwapped].tag = ASN_CONTEXT | 0;
3115 swapped[cSwapped].pvStructInfo =
3116 &info->dwRequireExplicitPolicySkipCerts;
3117 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3118 items[cItem].pvStructInfo = &swapped[cSwapped];
3119 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3120 cSwapped++;
3121 cItem++;
3123 if (info->fInhibitPolicyMapping)
3125 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3126 swapped[cSwapped].pvStructInfo =
3127 &info->dwInhibitPolicyMappingSkipCerts;
3128 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3129 items[cItem].pvStructInfo = &swapped[cSwapped];
3130 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3131 cSwapped++;
3132 cItem++;
3134 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3135 dwFlags, NULL, pbEncoded, pcbEncoded);
3137 __EXCEPT_PAGE_FAULT
3139 SetLastError(STATUS_ACCESS_VIOLATION);
3141 __ENDTRY
3142 return ret;
3145 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
3146 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3147 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3149 BOOL ret;
3151 __TRY
3153 const BLOBHEADER *hdr = pvStructInfo;
3155 if (hdr->bType != PUBLICKEYBLOB)
3157 SetLastError(E_INVALIDARG);
3158 ret = FALSE;
3160 else
3162 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
3163 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
3164 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
3165 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
3166 struct AsnEncodeSequenceItem items[] = {
3167 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
3168 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
3171 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3172 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3173 pcbEncoded);
3176 __EXCEPT_PAGE_FAULT
3178 SetLastError(STATUS_ACCESS_VIOLATION);
3179 ret = FALSE;
3181 __ENDTRY
3182 return ret;
3185 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
3186 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3187 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3189 BOOL ret;
3191 __TRY
3193 const CRYPT_DATA_BLOB *blob = pvStructInfo;
3194 DWORD bytesNeeded, lenBytes;
3196 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
3197 dwFlags, pEncodePara, pbEncoded, pbEncoded ? *pcbEncoded : 0);
3199 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
3200 bytesNeeded = 1 + lenBytes + blob->cbData;
3201 if (!pbEncoded)
3203 *pcbEncoded = bytesNeeded;
3204 ret = TRUE;
3206 else
3208 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3209 pcbEncoded, bytesNeeded)))
3211 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3212 pbEncoded = *(BYTE **)pbEncoded;
3213 *pbEncoded++ = ASN_OCTETSTRING;
3214 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
3215 pbEncoded += lenBytes;
3216 if (blob->cbData)
3217 memcpy(pbEncoded, blob->pbData, blob->cbData);
3221 __EXCEPT_PAGE_FAULT
3223 SetLastError(STATUS_ACCESS_VIOLATION);
3224 ret = FALSE;
3226 __ENDTRY
3227 TRACE("returning %d (%08x)\n", ret, GetLastError());
3228 return ret;
3231 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
3232 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3233 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3235 BOOL ret;
3237 __TRY
3239 const CRYPT_BIT_BLOB *blob = pvStructInfo;
3240 DWORD bytesNeeded, lenBytes, dataBytes;
3241 BYTE unusedBits;
3243 /* yep, MS allows cUnusedBits to be >= 8 */
3244 if (!blob->cUnusedBits)
3246 dataBytes = blob->cbData;
3247 unusedBits = 0;
3249 else if (blob->cbData * 8 > blob->cUnusedBits)
3251 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
3252 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
3253 blob->cUnusedBits;
3255 else
3257 dataBytes = 0;
3258 unusedBits = 0;
3260 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
3261 bytesNeeded = 1 + lenBytes + dataBytes + 1;
3262 if (!pbEncoded)
3264 *pcbEncoded = bytesNeeded;
3265 ret = TRUE;
3267 else
3269 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3270 pcbEncoded, bytesNeeded)))
3272 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3273 pbEncoded = *(BYTE **)pbEncoded;
3274 *pbEncoded++ = ASN_BITSTRING;
3275 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
3276 pbEncoded += lenBytes;
3277 *pbEncoded++ = unusedBits;
3278 if (dataBytes)
3280 BYTE mask = 0xff << unusedBits;
3282 if (dataBytes > 1)
3284 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
3285 pbEncoded += dataBytes - 1;
3287 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
3292 __EXCEPT_PAGE_FAULT
3294 SetLastError(STATUS_ACCESS_VIOLATION);
3295 ret = FALSE;
3297 __ENDTRY
3298 return ret;
3301 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
3302 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3303 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3305 BOOL ret;
3307 __TRY
3309 const CRYPT_BIT_BLOB *blob = pvStructInfo;
3310 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
3312 ret = TRUE;
3313 if (newBlob.cbData)
3315 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
3316 if (newBlob.pbData)
3318 DWORD i;
3320 for (i = 0; i < newBlob.cbData; i++)
3321 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
3323 else
3324 ret = FALSE;
3326 if (ret)
3327 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
3328 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3329 CryptMemFree(newBlob.pbData);
3331 __EXCEPT_PAGE_FAULT
3333 SetLastError(STATUS_ACCESS_VIOLATION);
3334 ret = FALSE;
3336 __ENDTRY
3337 return ret;
3340 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
3341 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3342 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3344 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
3346 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
3347 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3350 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
3351 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3352 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3354 BOOL ret;
3356 __TRY
3358 DWORD significantBytes, lenBytes, bytesNeeded;
3359 BYTE padByte = 0;
3360 BOOL pad = FALSE;
3361 const CRYPT_INTEGER_BLOB *blob = pvStructInfo;
3363 significantBytes = blob->cbData;
3364 if (significantBytes)
3366 if (blob->pbData[significantBytes - 1] & 0x80)
3368 /* negative, lop off leading (little-endian) 0xffs */
3369 for (; significantBytes > 0 &&
3370 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
3372 if (blob->pbData[significantBytes - 1] < 0x80)
3374 padByte = 0xff;
3375 pad = TRUE;
3378 else
3380 /* positive, lop off leading (little-endian) zeroes */
3381 for (; significantBytes > 0 &&
3382 !blob->pbData[significantBytes - 1]; significantBytes--)
3384 if (significantBytes == 0)
3385 significantBytes = 1;
3386 if (blob->pbData[significantBytes - 1] > 0x7f)
3388 padByte = 0;
3389 pad = TRUE;
3393 if (pad)
3394 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3395 else
3396 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3397 bytesNeeded = 1 + lenBytes + significantBytes;
3398 if (pad)
3399 bytesNeeded++;
3400 if (!pbEncoded)
3402 *pcbEncoded = bytesNeeded;
3403 ret = TRUE;
3405 else
3407 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3408 pcbEncoded, bytesNeeded)))
3410 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3411 pbEncoded = *(BYTE **)pbEncoded;
3412 *pbEncoded++ = ASN_INTEGER;
3413 if (pad)
3415 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3416 pbEncoded += lenBytes;
3417 *pbEncoded++ = padByte;
3419 else
3421 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3422 pbEncoded += lenBytes;
3424 for (; significantBytes > 0; significantBytes--)
3425 *(pbEncoded++) = blob->pbData[significantBytes - 1];
3429 __EXCEPT_PAGE_FAULT
3431 SetLastError(STATUS_ACCESS_VIOLATION);
3432 ret = FALSE;
3434 __ENDTRY
3435 return ret;
3438 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
3439 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3440 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3442 BOOL ret;
3444 __TRY
3446 DWORD significantBytes, lenBytes, bytesNeeded;
3447 BOOL pad = FALSE;
3448 const CRYPT_INTEGER_BLOB *blob = pvStructInfo;
3450 significantBytes = blob->cbData;
3451 if (significantBytes)
3453 /* positive, lop off leading (little-endian) zeroes */
3454 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
3455 significantBytes--)
3457 if (significantBytes == 0)
3458 significantBytes = 1;
3459 if (blob->pbData[significantBytes - 1] > 0x7f)
3460 pad = TRUE;
3462 if (pad)
3463 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3464 else
3465 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3466 bytesNeeded = 1 + lenBytes + significantBytes;
3467 if (pad)
3468 bytesNeeded++;
3469 if (!pbEncoded)
3471 *pcbEncoded = bytesNeeded;
3472 ret = TRUE;
3474 else
3476 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3477 pcbEncoded, bytesNeeded)))
3479 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3480 pbEncoded = *(BYTE **)pbEncoded;
3481 *pbEncoded++ = ASN_INTEGER;
3482 if (pad)
3484 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3485 pbEncoded += lenBytes;
3486 *pbEncoded++ = 0;
3488 else
3490 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3491 pbEncoded += lenBytes;
3493 for (; significantBytes > 0; significantBytes--)
3494 *(pbEncoded++) = blob->pbData[significantBytes - 1];
3498 __EXCEPT_PAGE_FAULT
3500 SetLastError(STATUS_ACCESS_VIOLATION);
3501 ret = FALSE;
3503 __ENDTRY
3504 return ret;
3507 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
3508 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3509 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3511 CRYPT_INTEGER_BLOB blob;
3512 BOOL ret;
3514 /* Encode as an unsigned integer, then change the tag to enumerated */
3515 blob.cbData = sizeof(DWORD);
3516 blob.pbData = (BYTE *)pvStructInfo;
3517 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
3518 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3519 if (ret && pbEncoded)
3521 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3522 pbEncoded = *(BYTE **)pbEncoded;
3523 pbEncoded[0] = ASN_ENUMERATED;
3525 return ret;
3528 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
3529 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3530 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3532 BOOL ret;
3534 __TRY
3536 SYSTEMTIME sysTime;
3537 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
3538 * temporary buffer because the output buffer is not NULL-terminated.
3540 char buf[16];
3541 static const DWORD bytesNeeded = sizeof(buf) - 1;
3543 if (!pbEncoded)
3545 *pcbEncoded = bytesNeeded;
3546 ret = TRUE;
3548 else
3550 /* Sanity check the year, this is a two-digit year format */
3551 ret = FileTimeToSystemTime(pvStructInfo, &sysTime);
3552 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
3554 SetLastError(CRYPT_E_BAD_ENCODE);
3555 ret = FALSE;
3557 if (ret)
3559 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3560 pbEncoded, pcbEncoded, bytesNeeded)))
3562 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3563 pbEncoded = *(BYTE **)pbEncoded;
3564 buf[0] = ASN_UTCTIME;
3565 buf[1] = bytesNeeded - 2;
3566 snprintf(buf + 2, sizeof(buf) - 2,
3567 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
3568 sysTime.wYear - 2000 : sysTime.wYear - 1900,
3569 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3570 sysTime.wMinute, sysTime.wSecond);
3571 memcpy(pbEncoded, buf, bytesNeeded);
3576 __EXCEPT_PAGE_FAULT
3578 SetLastError(STATUS_ACCESS_VIOLATION);
3579 ret = FALSE;
3581 __ENDTRY
3582 return ret;
3585 static BOOL CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
3586 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3587 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3589 BOOL ret;
3591 __TRY
3593 SYSTEMTIME sysTime;
3594 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
3595 * temporary buffer because the output buffer is not NULL-terminated.
3597 char buf[18];
3598 static const DWORD bytesNeeded = sizeof(buf) - 1;
3600 if (!pbEncoded)
3602 *pcbEncoded = bytesNeeded;
3603 ret = TRUE;
3605 else
3607 ret = FileTimeToSystemTime(pvStructInfo, &sysTime);
3608 if (ret)
3609 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3610 pcbEncoded, bytesNeeded);
3611 if (ret)
3613 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3614 pbEncoded = *(BYTE **)pbEncoded;
3615 buf[0] = ASN_GENERALTIME;
3616 buf[1] = bytesNeeded - 2;
3617 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
3618 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3619 sysTime.wMinute, sysTime.wSecond);
3620 memcpy(pbEncoded, buf, bytesNeeded);
3624 __EXCEPT_PAGE_FAULT
3626 SetLastError(STATUS_ACCESS_VIOLATION);
3627 ret = FALSE;
3629 __ENDTRY
3630 return ret;
3633 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
3634 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3635 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3637 BOOL ret;
3639 __TRY
3641 SYSTEMTIME sysTime;
3643 /* Check the year, if it's in the UTCTime range call that encode func */
3644 if (!FileTimeToSystemTime(pvStructInfo, &sysTime))
3645 return FALSE;
3646 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
3647 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
3648 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3649 else
3650 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
3651 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
3652 pcbEncoded);
3654 __EXCEPT_PAGE_FAULT
3656 SetLastError(STATUS_ACCESS_VIOLATION);
3657 ret = FALSE;
3659 __ENDTRY
3660 return ret;
3663 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
3664 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3665 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3667 BOOL ret;
3669 __TRY
3671 DWORD bytesNeeded, dataLen, lenBytes, i;
3672 const CRYPT_SEQUENCE_OF_ANY *seq = pvStructInfo;
3674 for (i = 0, dataLen = 0; i < seq->cValue; i++)
3675 dataLen += seq->rgValue[i].cbData;
3676 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3677 bytesNeeded = 1 + lenBytes + dataLen;
3678 if (!pbEncoded)
3680 *pcbEncoded = bytesNeeded;
3681 ret = TRUE;
3683 else
3685 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3686 pcbEncoded, bytesNeeded)))
3688 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3689 pbEncoded = *(BYTE **)pbEncoded;
3690 *pbEncoded++ = ASN_SEQUENCEOF;
3691 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
3692 pbEncoded += lenBytes;
3693 for (i = 0; i < seq->cValue; i++)
3695 memcpy(pbEncoded, seq->rgValue[i].pbData,
3696 seq->rgValue[i].cbData);
3697 pbEncoded += seq->rgValue[i].cbData;
3702 __EXCEPT_PAGE_FAULT
3704 SetLastError(STATUS_ACCESS_VIOLATION);
3705 ret = FALSE;
3707 __ENDTRY
3708 return ret;
3711 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
3712 BYTE *pbEncoded, DWORD *pcbEncoded)
3714 BOOL ret = TRUE;
3715 struct AsnEncodeSequenceItem items[3] = { { 0 } };
3716 struct AsnConstructedItem constructed = { 0 };
3717 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
3718 DWORD cItem = 0, cSwapped = 0;
3720 switch (distPoint->DistPointName.dwDistPointNameChoice)
3722 case CRL_DIST_POINT_NO_NAME:
3723 /* do nothing */
3724 break;
3725 case CRL_DIST_POINT_FULL_NAME:
3726 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3727 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
3728 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3729 constructed.tag = 0;
3730 constructed.pvStructInfo = &swapped[cSwapped];
3731 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3732 items[cItem].pvStructInfo = &constructed;
3733 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3734 cSwapped++;
3735 cItem++;
3736 break;
3737 case CRL_DIST_POINT_ISSUER_RDN_NAME:
3738 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3739 ret = FALSE;
3740 break;
3741 default:
3742 ret = FALSE;
3744 if (ret && distPoint->ReasonFlags.cbData)
3746 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3747 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
3748 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3749 items[cItem].pvStructInfo = &swapped[cSwapped];
3750 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3751 cSwapped++;
3752 cItem++;
3754 if (ret && distPoint->CRLIssuer.cAltEntry)
3756 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
3757 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
3758 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3759 items[cItem].pvStructInfo = &swapped[cSwapped];
3760 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3761 cSwapped++;
3762 cItem++;
3764 if (ret)
3765 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
3766 pbEncoded, pcbEncoded);
3767 return ret;
3770 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
3771 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3772 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3774 BOOL ret;
3776 __TRY
3778 const CRL_DIST_POINTS_INFO *info = pvStructInfo;
3780 if (!info->cDistPoint)
3782 SetLastError(E_INVALIDARG);
3783 ret = FALSE;
3785 else
3787 DWORD bytesNeeded, dataLen, lenBytes, i;
3789 ret = TRUE;
3790 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
3792 DWORD len;
3794 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
3795 &len);
3796 if (ret)
3797 dataLen += len;
3798 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
3800 /* Have to propagate index of failing character */
3801 *pcbEncoded = len;
3804 if (ret)
3806 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3807 bytesNeeded = 1 + lenBytes + dataLen;
3808 if (!pbEncoded)
3810 *pcbEncoded = bytesNeeded;
3811 ret = TRUE;
3813 else
3815 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3816 pbEncoded, pcbEncoded, bytesNeeded)))
3818 BYTE *out;
3820 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3821 pbEncoded = *(BYTE **)pbEncoded;
3822 out = pbEncoded;
3823 *out++ = ASN_SEQUENCEOF;
3824 CRYPT_EncodeLen(dataLen, out, &lenBytes);
3825 out += lenBytes;
3826 for (i = 0; ret && i < info->cDistPoint; i++)
3828 DWORD len = dataLen;
3830 ret = CRYPT_AsnEncodeDistPoint(
3831 &info->rgDistPoint[i], out, &len);
3832 if (ret)
3834 out += len;
3835 dataLen -= len;
3838 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
3839 CRYPT_FreeSpace(pEncodePara, pbEncoded);
3845 __EXCEPT_PAGE_FAULT
3847 SetLastError(STATUS_ACCESS_VIOLATION);
3848 ret = FALSE;
3850 __ENDTRY
3851 return ret;
3854 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3855 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3856 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3858 BOOL ret;
3860 __TRY
3862 const CERT_ENHKEY_USAGE *usage = pvStructInfo;
3863 DWORD bytesNeeded = 0, lenBytes, size, i;
3865 ret = TRUE;
3866 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3868 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3869 usage->rgpszUsageIdentifier[i],
3870 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
3871 if (ret)
3872 bytesNeeded += size;
3874 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3875 bytesNeeded += 1 + lenBytes;
3876 if (ret)
3878 if (!pbEncoded)
3879 *pcbEncoded = bytesNeeded;
3880 else
3882 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3883 pbEncoded, pcbEncoded, bytesNeeded)))
3885 BYTE *out;
3887 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3888 pbEncoded = *(BYTE **)pbEncoded;
3889 out = pbEncoded;
3890 *out++ = ASN_SEQUENCEOF;
3891 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
3892 out += lenBytes;
3893 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3895 size = bytesNeeded;
3896 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3897 usage->rgpszUsageIdentifier[i],
3898 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, out, &size);
3899 if (ret)
3901 out += size;
3902 bytesNeeded -= size;
3905 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
3906 CRYPT_FreeSpace(pEncodePara, pbEncoded);
3911 __EXCEPT_PAGE_FAULT
3913 SetLastError(STATUS_ACCESS_VIOLATION);
3914 ret = FALSE;
3916 __ENDTRY
3917 return ret;
3920 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
3921 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3922 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3924 BOOL ret;
3926 __TRY
3928 const CRL_ISSUING_DIST_POINT *point = pvStructInfo;
3929 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3930 struct AsnConstructedItem constructed = { 0 };
3931 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3932 DWORD cItem = 0, cSwapped = 0;
3934 ret = TRUE;
3935 switch (point->DistPointName.dwDistPointNameChoice)
3937 case CRL_DIST_POINT_NO_NAME:
3938 /* do nothing */
3939 break;
3940 case CRL_DIST_POINT_FULL_NAME:
3941 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3942 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3943 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3944 constructed.tag = 0;
3945 constructed.pvStructInfo = &swapped[cSwapped];
3946 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3947 items[cItem].pvStructInfo = &constructed;
3948 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3949 cSwapped++;
3950 cItem++;
3951 break;
3952 default:
3953 SetLastError(E_INVALIDARG);
3954 ret = FALSE;
3956 if (ret && point->fOnlyContainsUserCerts)
3958 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3959 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3960 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3961 items[cItem].pvStructInfo = &swapped[cSwapped];
3962 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3963 cSwapped++;
3964 cItem++;
3966 if (ret && point->fOnlyContainsCACerts)
3968 swapped[cSwapped].tag = ASN_CONTEXT | 2;
3969 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3970 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3971 items[cItem].pvStructInfo = &swapped[cSwapped];
3972 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3973 cSwapped++;
3974 cItem++;
3976 if (ret && point->OnlySomeReasonFlags.cbData)
3978 swapped[cSwapped].tag = ASN_CONTEXT | 3;
3979 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3980 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3981 items[cItem].pvStructInfo = &swapped[cSwapped];
3982 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3983 cSwapped++;
3984 cItem++;
3986 if (ret && point->fIndirectCRL)
3988 swapped[cSwapped].tag = ASN_CONTEXT | 4;
3989 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
3990 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3991 items[cItem].pvStructInfo = &swapped[cSwapped];
3992 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3993 cSwapped++;
3994 cItem++;
3996 if (ret)
3997 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3998 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4000 __EXCEPT_PAGE_FAULT
4002 SetLastError(STATUS_ACCESS_VIOLATION);
4003 ret = FALSE;
4005 __ENDTRY
4006 return ret;
4009 static BOOL CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType,
4010 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4011 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4013 BOOL ret;
4014 const CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
4015 struct AsnEncodeSequenceItem items[3] = {
4016 { &subtree->Base, CRYPT_AsnEncodeAltNameEntry, 0 },
4017 { 0 }
4019 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4020 DWORD cItem = 1, cSwapped = 0;
4022 if (subtree->dwMinimum)
4024 swapped[cSwapped].tag = ASN_CONTEXT | 0;
4025 swapped[cSwapped].pvStructInfo = &subtree->dwMinimum;
4026 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
4027 items[cItem].pvStructInfo = &swapped[cSwapped];
4028 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4029 cSwapped++;
4030 cItem++;
4032 if (subtree->fMaximum)
4034 swapped[cSwapped].tag = ASN_CONTEXT | 1;
4035 swapped[cSwapped].pvStructInfo = &subtree->dwMaximum;
4036 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
4037 items[cItem].pvStructInfo = &swapped[cSwapped];
4038 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4039 cSwapped++;
4040 cItem++;
4042 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags,
4043 pEncodePara, pbEncoded, pcbEncoded);
4044 return ret;
4047 static BOOL WINAPI CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType,
4048 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4049 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4051 BOOL ret = FALSE;
4052 CRYPT_BLOB_ARRAY permitted = { 0, NULL }, excluded = { 0, NULL };
4054 TRACE("%p\n", pvStructInfo);
4056 __TRY
4058 const CERT_NAME_CONSTRAINTS_INFO *constraints = pvStructInfo;
4059 struct AsnEncodeSequenceItem items[2] = { { 0 } };
4060 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4061 DWORD i, cItem = 0, cSwapped = 0;
4063 ret = TRUE;
4064 if (constraints->cPermittedSubtree)
4066 permitted.rgBlob = CryptMemAlloc(
4067 constraints->cPermittedSubtree * sizeof(CRYPT_DER_BLOB));
4068 if (permitted.rgBlob)
4070 permitted.cBlob = constraints->cPermittedSubtree;
4071 memset(permitted.rgBlob, 0,
4072 permitted.cBlob * sizeof(CRYPT_DER_BLOB));
4073 for (i = 0; ret && i < permitted.cBlob; i++)
4074 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
4075 NULL, &constraints->rgPermittedSubtree[i],
4076 CRYPT_ENCODE_ALLOC_FLAG, NULL,
4077 (BYTE *)&permitted.rgBlob[i].pbData,
4078 &permitted.rgBlob[i].cbData);
4079 if (ret)
4081 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4082 swapped[cSwapped].pvStructInfo = &permitted;
4083 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
4084 items[cItem].pvStructInfo = &swapped[cSwapped];
4085 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4086 cSwapped++;
4087 cItem++;
4090 else
4091 ret = FALSE;
4093 if (constraints->cExcludedSubtree)
4095 excluded.rgBlob = CryptMemAlloc(
4096 constraints->cExcludedSubtree * sizeof(CRYPT_DER_BLOB));
4097 if (excluded.rgBlob)
4099 excluded.cBlob = constraints->cExcludedSubtree;
4100 memset(excluded.rgBlob, 0,
4101 excluded.cBlob * sizeof(CRYPT_DER_BLOB));
4102 for (i = 0; ret && i < excluded.cBlob; i++)
4103 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
4104 NULL, &constraints->rgExcludedSubtree[i],
4105 CRYPT_ENCODE_ALLOC_FLAG, NULL,
4106 (BYTE *)&excluded.rgBlob[i].pbData,
4107 &excluded.rgBlob[i].cbData);
4108 if (ret)
4110 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4111 swapped[cSwapped].pvStructInfo = &excluded;
4112 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
4113 items[cItem].pvStructInfo = &swapped[cSwapped];
4114 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4115 cSwapped++;
4116 cItem++;
4119 else
4120 ret = FALSE;
4122 if (ret)
4123 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4124 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4125 for (i = 0; i < permitted.cBlob; i++)
4126 LocalFree(permitted.rgBlob[i].pbData);
4127 for (i = 0; i < excluded.cBlob; i++)
4128 LocalFree(excluded.rgBlob[i].pbData);
4130 __EXCEPT_PAGE_FAULT
4132 SetLastError(STATUS_ACCESS_VIOLATION);
4134 __ENDTRY
4135 CryptMemFree(permitted.rgBlob);
4136 CryptMemFree(excluded.rgBlob);
4137 TRACE("returning %d\n", ret);
4138 return ret;
4141 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
4142 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
4143 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
4144 DWORD *pcbEncoded)
4146 BOOL ret;
4147 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
4148 struct AsnEncodeSequenceItem items[] = {
4149 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
4150 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
4153 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4154 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
4155 pcbEncoded);
4156 return ret;
4159 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
4160 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4161 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4163 BOOL ret = FALSE;
4165 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
4167 SetLastError(E_INVALIDARG);
4168 return FALSE;
4171 __TRY
4173 const CMSG_SIGNER_INFO *info = pvStructInfo;
4175 if (!info->Issuer.cbData)
4176 SetLastError(E_INVALIDARG);
4177 else
4179 struct AsnEncodeSequenceItem items[7] = {
4180 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4181 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
4182 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
4183 0 },
4185 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4186 DWORD cItem = 3, cSwapped = 0;
4188 if (info->AuthAttrs.cAttr)
4190 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4191 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
4192 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4193 items[cItem].pvStructInfo = &swapped[cSwapped];
4194 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4195 cSwapped++;
4196 cItem++;
4198 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
4199 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4200 cItem++;
4201 items[cItem].pvStructInfo = &info->EncryptedHash;
4202 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
4203 cItem++;
4204 if (info->UnauthAttrs.cAttr)
4206 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4207 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
4208 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4209 items[cItem].pvStructInfo = &swapped[cSwapped];
4210 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4211 cSwapped++;
4212 cItem++;
4214 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4215 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4218 __EXCEPT_PAGE_FAULT
4220 SetLastError(STATUS_ACCESS_VIOLATION);
4222 __ENDTRY
4223 return ret;
4226 static BOOL WINAPI CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType,
4227 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4228 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4230 BOOL ret = FALSE;
4232 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
4234 SetLastError(E_INVALIDARG);
4235 return FALSE;
4238 __TRY
4240 const CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
4242 if (info->SignerId.dwIdChoice != CERT_ID_ISSUER_SERIAL_NUMBER &&
4243 info->SignerId.dwIdChoice != CERT_ID_KEY_IDENTIFIER)
4244 SetLastError(E_INVALIDARG);
4245 else if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER &&
4246 !info->SignerId.u.IssuerSerialNumber.Issuer.cbData)
4247 SetLastError(E_INVALIDARG);
4248 else
4250 struct AsnEncodeSequenceItem items[7] = {
4251 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4253 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
4254 DWORD cItem = 1, cSwapped = 0;
4256 if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
4258 items[cItem].pvStructInfo =
4259 &info->SignerId.u.IssuerSerialNumber.Issuer;
4260 items[cItem].encodeFunc =
4261 CRYPT_AsnEncodeIssuerSerialNumber;
4262 cItem++;
4264 else
4266 swapped[cSwapped].tag = ASN_CONTEXT | 0;
4267 swapped[cSwapped].pvStructInfo = &info->SignerId.u.KeyId;
4268 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
4269 items[cItem].pvStructInfo = &swapped[cSwapped];
4270 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4271 cSwapped++;
4272 cItem++;
4274 items[cItem].pvStructInfo = &info->HashAlgorithm;
4275 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4276 cItem++;
4277 if (info->AuthAttrs.cAttr)
4279 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4280 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
4281 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4282 items[cItem].pvStructInfo = &swapped[cSwapped];
4283 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4284 cSwapped++;
4285 cItem++;
4287 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
4288 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4289 cItem++;
4290 items[cItem].pvStructInfo = &info->EncryptedHash;
4291 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
4292 cItem++;
4293 if (info->UnauthAttrs.cAttr)
4295 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4296 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
4297 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4298 items[cItem].pvStructInfo = &swapped[cSwapped];
4299 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4300 cSwapped++;
4301 cItem++;
4303 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4304 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4307 __EXCEPT_PAGE_FAULT
4309 SetLastError(STATUS_ACCESS_VIOLATION);
4311 __ENDTRY
4312 return ret;
4315 BOOL CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
4316 DWORD *pcbData)
4318 struct AsnEncodeSequenceItem items[7] = {
4319 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
4321 struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 };
4322 struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 };
4323 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4324 DWORD cItem = 1, cSwapped = 0;
4325 BOOL ret = TRUE;
4327 if (signedInfo->cSignerInfo)
4329 digestAlgorithmsSet.cItems = signedInfo->cSignerInfo;
4330 digestAlgorithmsSet.items = signedInfo->rgSignerInfo;
4331 digestAlgorithmsSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
4332 digestAlgorithmsSet.itemOffset =
4333 offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm);
4334 digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4335 items[cItem].pvStructInfo = &digestAlgorithmsSet;
4336 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4337 cItem++;
4339 items[cItem].pvStructInfo = &signedInfo->content;
4340 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal;
4341 cItem++;
4342 if (signedInfo->cCertEncoded)
4344 certSet.cItems = signedInfo->cCertEncoded;
4345 certSet.items = signedInfo->rgCertEncoded;
4346 certSet.itemSize = sizeof(CERT_BLOB);
4347 certSet.itemOffset = 0;
4348 certSet.encode = CRYPT_CopyEncodedBlob;
4349 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0;
4350 swapped[cSwapped].pvStructInfo = &certSet;
4351 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4352 items[cItem].pvStructInfo = &swapped[cSwapped];
4353 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4354 cSwapped++;
4355 cItem++;
4357 if (signedInfo->cCrlEncoded)
4359 crlSet.cItems = signedInfo->cCrlEncoded;
4360 crlSet.items = signedInfo->rgCrlEncoded;
4361 crlSet.itemSize = sizeof(CRL_BLOB);
4362 crlSet.itemOffset = 0;
4363 crlSet.encode = CRYPT_CopyEncodedBlob;
4364 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
4365 swapped[cSwapped].pvStructInfo = &crlSet;
4366 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4367 items[cItem].pvStructInfo = &swapped[cSwapped];
4368 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4369 cSwapped++;
4370 cItem++;
4372 if (ret && signedInfo->cSignerInfo)
4374 signerSet.cItems = signedInfo->cSignerInfo;
4375 signerSet.items = signedInfo->rgSignerInfo;
4376 signerSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
4377 signerSet.itemOffset = 0;
4378 signerSet.encode = CRYPT_AsnEncodeCMSSignerInfo;
4379 items[cItem].pvStructInfo = &signerSet;
4380 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4381 cItem++;
4383 if (ret)
4384 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
4385 items, cItem, 0, NULL, pvData, pcbData);
4387 return ret;
4390 static BOOL WINAPI CRYPT_AsnEncodeRecipientInfo(DWORD dwCertEncodingType,
4391 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4392 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4394 const CMSG_KEY_TRANS_RECIPIENT_INFO *info = pvStructInfo;
4395 struct AsnEncodeSequenceItem items[] = {
4396 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4397 { &info->RecipientId.u.IssuerSerialNumber,
4398 CRYPT_AsnEncodeIssuerSerialNumber, 0 },
4399 { &info->KeyEncryptionAlgorithm,
4400 CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
4401 { &info->EncryptedKey, CRYPT_AsnEncodeOctets, 0 },
4404 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4405 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
4406 pcbEncoded);
4409 static BOOL WINAPI CRYPT_AsnEncodeEncryptedContentInfo(DWORD dwCertEncodingType,
4410 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4411 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4413 const CRYPT_ENCRYPTED_CONTENT_INFO *info = pvStructInfo;
4414 struct AsnEncodeTagSwappedItem swapped = { ASN_CONTEXT | 0,
4415 &info->encryptedContent, CRYPT_AsnEncodeOctets };
4416 struct AsnEncodeSequenceItem items[] = {
4417 { info->contentType, CRYPT_AsnEncodeOid, 0 },
4418 { &info->contentEncryptionAlgorithm,
4419 CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
4420 { &swapped, CRYPT_AsnEncodeSwapTag, 0 },
4423 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4424 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
4425 pcbEncoded);
4428 BOOL CRYPT_AsnEncodePKCSEnvelopedData(const CRYPT_ENVELOPED_DATA *envelopedData,
4429 void *pvData, DWORD *pcbData)
4431 struct DERSetDescriptor recipientInfosSet = { envelopedData->cRecipientInfo,
4432 envelopedData->rgRecipientInfo, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO), 0,
4433 CRYPT_AsnEncodeRecipientInfo };
4434 struct AsnEncodeSequenceItem items[] = {
4435 { &envelopedData->version, CRYPT_AsnEncodeInt, 0 },
4436 { &recipientInfosSet, CRYPT_DEREncodeItemsAsSet, 0 },
4437 { &envelopedData->encryptedContentInfo,
4438 CRYPT_AsnEncodeEncryptedContentInfo, 0 },
4441 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
4442 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
4445 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
4446 LPCSTR lpszStructType)
4448 CryptEncodeObjectExFunc encodeFunc = NULL;
4450 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4451 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4453 SetLastError(ERROR_FILE_NOT_FOUND);
4454 return NULL;
4457 if (IS_INTOID(lpszStructType))
4459 switch (LOWORD(lpszStructType))
4461 case LOWORD(X509_CERT):
4462 encodeFunc = CRYPT_AsnEncodeCert;
4463 break;
4464 case LOWORD(X509_CERT_TO_BE_SIGNED):
4465 encodeFunc = CRYPT_AsnEncodeCertInfo;
4466 break;
4467 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
4468 encodeFunc = CRYPT_AsnEncodeCRLInfo;
4469 break;
4470 case LOWORD(X509_EXTENSIONS):
4471 encodeFunc = CRYPT_AsnEncodeExtensions;
4472 break;
4473 case LOWORD(X509_NAME_VALUE):
4474 encodeFunc = CRYPT_AsnEncodeNameValue;
4475 break;
4476 case LOWORD(X509_NAME):
4477 encodeFunc = CRYPT_AsnEncodeName;
4478 break;
4479 case LOWORD(X509_PUBLIC_KEY_INFO):
4480 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
4481 break;
4482 case LOWORD(X509_AUTHORITY_KEY_ID):
4483 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
4484 break;
4485 case LOWORD(X509_ALTERNATE_NAME):
4486 encodeFunc = CRYPT_AsnEncodeAltName;
4487 break;
4488 case LOWORD(X509_BASIC_CONSTRAINTS):
4489 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
4490 break;
4491 case LOWORD(X509_BASIC_CONSTRAINTS2):
4492 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
4493 break;
4494 case LOWORD(X509_CERT_POLICIES):
4495 encodeFunc = CRYPT_AsnEncodeCertPolicies;
4496 break;
4497 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
4498 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
4499 break;
4500 case LOWORD(X509_UNICODE_NAME):
4501 encodeFunc = CRYPT_AsnEncodeUnicodeName;
4502 break;
4503 case LOWORD(PKCS_CONTENT_INFO):
4504 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
4505 break;
4506 case LOWORD(PKCS_ATTRIBUTE):
4507 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
4508 break;
4509 case LOWORD(X509_UNICODE_NAME_VALUE):
4510 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
4511 break;
4512 case LOWORD(X509_OCTET_STRING):
4513 encodeFunc = CRYPT_AsnEncodeOctets;
4514 break;
4515 case LOWORD(X509_BITS):
4516 case LOWORD(X509_KEY_USAGE):
4517 encodeFunc = CRYPT_AsnEncodeBits;
4518 break;
4519 case LOWORD(X509_INTEGER):
4520 encodeFunc = CRYPT_AsnEncodeInt;
4521 break;
4522 case LOWORD(X509_MULTI_BYTE_INTEGER):
4523 encodeFunc = CRYPT_AsnEncodeInteger;
4524 break;
4525 case LOWORD(X509_MULTI_BYTE_UINT):
4526 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
4527 break;
4528 case LOWORD(X509_ENUMERATED):
4529 encodeFunc = CRYPT_AsnEncodeEnumerated;
4530 break;
4531 case LOWORD(X509_CHOICE_OF_TIME):
4532 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
4533 break;
4534 case LOWORD(X509_AUTHORITY_KEY_ID2):
4535 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
4536 break;
4537 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
4538 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
4539 break;
4540 case LOWORD(X509_SEQUENCE_OF_ANY):
4541 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
4542 break;
4543 case LOWORD(PKCS_UTC_TIME):
4544 encodeFunc = CRYPT_AsnEncodeUtcTime;
4545 break;
4546 case LOWORD(X509_CRL_DIST_POINTS):
4547 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
4548 break;
4549 case LOWORD(X509_ENHANCED_KEY_USAGE):
4550 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
4551 break;
4552 case LOWORD(PKCS_CTL):
4553 encodeFunc = CRYPT_AsnEncodeCTL;
4554 break;
4555 case LOWORD(PKCS_SMIME_CAPABILITIES):
4556 encodeFunc = CRYPT_AsnEncodeSMIMECapabilities;
4557 break;
4558 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
4559 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
4560 break;
4561 case LOWORD(PKCS_ATTRIBUTES):
4562 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4563 break;
4564 case LOWORD(X509_ISSUING_DIST_POINT):
4565 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
4566 break;
4567 case LOWORD(X509_NAME_CONSTRAINTS):
4568 encodeFunc = CRYPT_AsnEncodeNameConstraints;
4569 break;
4570 case LOWORD(X509_POLICY_MAPPINGS):
4571 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
4572 break;
4573 case LOWORD(X509_POLICY_CONSTRAINTS):
4574 encodeFunc = CRYPT_AsnEncodeCertPolicyConstraints;
4575 break;
4576 case LOWORD(PKCS7_SIGNER_INFO):
4577 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
4578 break;
4579 case LOWORD(CMS_SIGNER_INFO):
4580 encodeFunc = CRYPT_AsnEncodeCMSSignerInfo;
4581 break;
4584 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4585 encodeFunc = CRYPT_AsnEncodeExtensions;
4586 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4587 encodeFunc = CRYPT_AsnEncodeUtcTime;
4588 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
4589 encodeFunc = CRYPT_AsnEncodeUtcTime;
4590 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4591 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
4592 else if (!strcmp(lpszStructType, szOID_LEGACY_POLICY_MAPPINGS))
4593 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
4594 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4595 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
4596 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4597 encodeFunc = CRYPT_AsnEncodeEnumerated;
4598 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4599 encodeFunc = CRYPT_AsnEncodeBits;
4600 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4601 encodeFunc = CRYPT_AsnEncodeOctets;
4602 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4603 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
4604 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4605 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
4606 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4607 encodeFunc = CRYPT_AsnEncodeAltName;
4608 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4609 encodeFunc = CRYPT_AsnEncodeAltName;
4610 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4611 encodeFunc = CRYPT_AsnEncodeAltName;
4612 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4613 encodeFunc = CRYPT_AsnEncodeAltName;
4614 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4615 encodeFunc = CRYPT_AsnEncodeAltName;
4616 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4617 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
4618 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
4619 encodeFunc = CRYPT_AsnEncodeCertPolicies;
4620 else if (!strcmp(lpszStructType, szOID_POLICY_MAPPINGS))
4621 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
4622 else if (!strcmp(lpszStructType, szOID_POLICY_CONSTRAINTS))
4623 encodeFunc = CRYPT_AsnEncodeCertPolicyConstraints;
4624 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4625 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
4626 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4627 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
4628 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
4629 encodeFunc = CRYPT_AsnEncodeNameConstraints;
4630 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
4631 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
4632 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
4633 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
4634 else if (!strcmp(lpszStructType, szOID_CTL))
4635 encodeFunc = CRYPT_AsnEncodeCTL;
4636 return encodeFunc;
4639 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType,
4640 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4642 static HCRYPTOIDFUNCSET set = NULL;
4643 CryptEncodeObjectFunc encodeFunc = NULL;
4645 if (!set)
4646 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
4647 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4648 (void **)&encodeFunc, hFunc);
4649 return encodeFunc;
4652 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType,
4653 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4655 static HCRYPTOIDFUNCSET set = NULL;
4656 CryptEncodeObjectExFunc encodeFunc = NULL;
4658 if (!set)
4659 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
4660 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4661 (void **)&encodeFunc, hFunc);
4662 return encodeFunc;
4665 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4666 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
4668 BOOL ret = FALSE;
4669 HCRYPTOIDFUNCADDR hFunc = NULL;
4670 CryptEncodeObjectFunc pCryptEncodeObject = NULL;
4671 CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL;
4673 TRACE_(crypt)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
4674 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
4675 pcbEncoded);
4677 if (!pbEncoded && !pcbEncoded)
4679 SetLastError(ERROR_INVALID_PARAMETER);
4680 return FALSE;
4683 if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType,
4684 lpszStructType)))
4686 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4687 debugstr_a(lpszStructType));
4688 pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType,
4689 lpszStructType, &hFunc);
4690 if (!pCryptEncodeObject)
4691 pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType,
4692 lpszStructType, &hFunc);
4694 if (pCryptEncodeObject)
4695 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4696 pvStructInfo, pbEncoded, pcbEncoded);
4697 else if (pCryptEncodeObjectEx)
4698 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
4699 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
4700 if (hFunc)
4701 CryptFreeOIDFunctionAddress(hFunc, 0);
4702 TRACE_(crypt)("returning %d\n", ret);
4703 return ret;
4706 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4707 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
4708 void *pvEncoded, DWORD *pcbEncoded)
4710 BOOL ret = FALSE;
4711 HCRYPTOIDFUNCADDR hFunc = NULL;
4712 CryptEncodeObjectExFunc encodeFunc = NULL;
4714 TRACE_(crypt)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
4715 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
4716 pvEncoded, pcbEncoded);
4718 if (!pvEncoded && !pcbEncoded)
4720 SetLastError(ERROR_INVALID_PARAMETER);
4721 return FALSE;
4724 SetLastError(NOERROR);
4725 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
4726 if (!pvEncoded) {
4727 SetLastError(ERROR_INVALID_PARAMETER);
4728 return FALSE;
4730 *(BYTE **)pvEncoded = NULL;
4732 encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType);
4733 if (!encodeFunc)
4735 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4736 debugstr_a(lpszStructType));
4737 encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType,
4738 &hFunc);
4740 if (encodeFunc)
4741 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
4742 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
4743 else
4745 CryptEncodeObjectFunc pCryptEncodeObject =
4746 CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4748 if (pCryptEncodeObject)
4750 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
4752 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4753 pvStructInfo, NULL, pcbEncoded);
4754 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
4755 pvEncoded, pcbEncoded, *pcbEncoded)))
4756 ret = pCryptEncodeObject(dwCertEncodingType,
4757 lpszStructType, pvStructInfo, *(BYTE **)pvEncoded,
4758 pcbEncoded);
4760 else
4761 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4762 pvStructInfo, pvEncoded, pcbEncoded);
4765 if (hFunc)
4766 CryptFreeOIDFunctionAddress(hFunc, 0);
4767 TRACE_(crypt)("returning %d\n", ret);
4768 return ret;
4771 BOOL WINAPI PFXExportCertStore(HCERTSTORE hStore, CRYPT_DATA_BLOB *pPFX,
4772 LPCWSTR szPassword, DWORD dwFlags)
4774 return PFXExportCertStoreEx(hStore, pPFX, szPassword, NULL, dwFlags);
4777 BOOL WINAPI PFXExportCertStoreEx(HCERTSTORE hStore, CRYPT_DATA_BLOB *pPFX,
4778 LPCWSTR szPassword, void *pvReserved, DWORD dwFlags)
4780 FIXME_(crypt)("(%p, %p, %p, %p, %08x): stub\n", hStore, pPFX, szPassword,
4781 pvReserved, dwFlags);
4782 return FALSE;
4785 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
4786 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4788 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
4789 NULL, 0, NULL, pInfo, pcbInfo);
4792 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
4793 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
4794 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4796 BOOL ret;
4797 HCRYPTKEY key;
4798 static CHAR oid[] = szOID_RSA_RSA;
4800 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
4801 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
4802 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
4804 if (!pszPublicKeyObjId)
4805 pszPublicKeyObjId = oid;
4806 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
4808 DWORD keySize = 0;
4810 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
4811 if (ret)
4813 LPBYTE pubKey = CryptMemAlloc(keySize);
4815 if (pubKey)
4817 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
4818 &keySize);
4819 if (ret)
4821 DWORD encodedLen = 0;
4823 ret = CryptEncodeObject(dwCertEncodingType,
4824 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
4825 if (ret)
4827 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
4828 strlen(pszPublicKeyObjId) + 1 + encodedLen;
4830 if (!pInfo)
4831 *pcbInfo = sizeNeeded;
4832 else if (*pcbInfo < sizeNeeded)
4834 SetLastError(ERROR_MORE_DATA);
4835 *pcbInfo = sizeNeeded;
4836 ret = FALSE;
4838 else
4840 *pcbInfo = sizeNeeded;
4841 pInfo->Algorithm.pszObjId = (char *)pInfo +
4842 sizeof(CERT_PUBLIC_KEY_INFO);
4843 lstrcpyA(pInfo->Algorithm.pszObjId,
4844 pszPublicKeyObjId);
4845 pInfo->Algorithm.Parameters.cbData = 0;
4846 pInfo->Algorithm.Parameters.pbData = NULL;
4847 pInfo->PublicKey.pbData =
4848 (BYTE *)pInfo->Algorithm.pszObjId
4849 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
4850 pInfo->PublicKey.cbData = encodedLen;
4851 pInfo->PublicKey.cUnusedBits = 0;
4852 ret = CryptEncodeObject(dwCertEncodingType,
4853 RSA_CSP_PUBLICKEYBLOB, pubKey,
4854 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
4858 CryptMemFree(pubKey);
4860 else
4861 ret = FALSE;
4863 CryptDestroyKey(key);
4865 return ret;
4868 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
4869 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
4870 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
4872 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
4873 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
4874 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4876 static HCRYPTOIDFUNCSET set = NULL;
4877 BOOL ret;
4878 ExportPublicKeyInfoExFunc exportFunc = NULL;
4879 HCRYPTOIDFUNCADDR hFunc = NULL;
4881 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
4882 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
4883 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
4885 if (!hCryptProv)
4887 SetLastError(ERROR_INVALID_PARAMETER);
4888 return FALSE;
4891 if (pszPublicKeyObjId)
4893 if (!set)
4894 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
4896 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
4897 0, (void **)&exportFunc, &hFunc);
4899 if (!exportFunc)
4900 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
4901 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
4902 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
4903 if (hFunc)
4904 CryptFreeOIDFunctionAddress(hFunc, 0);
4905 return ret;
4908 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
4909 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
4911 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
4912 0, 0, NULL, phKey);
4915 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
4916 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4917 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
4919 BOOL ret;
4920 DWORD pubKeySize = 0;
4922 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
4923 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
4925 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
4926 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
4927 if (ret)
4929 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
4931 if (pubKey)
4933 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
4934 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
4935 &pubKeySize);
4936 if (ret)
4938 if(aiKeyAlg)
4939 ((BLOBHEADER*)pubKey)->aiKeyAlg = aiKeyAlg;
4940 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
4941 phKey);
4943 CryptMemFree(pubKey);
4945 else
4946 ret = FALSE;
4948 return ret;
4951 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
4952 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4953 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
4955 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
4956 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4957 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
4959 static HCRYPTOIDFUNCSET set = NULL;
4960 BOOL ret;
4961 ImportPublicKeyInfoExFunc importFunc = NULL;
4962 HCRYPTOIDFUNCADDR hFunc = NULL;
4964 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
4965 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
4967 if (!set)
4968 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
4969 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
4970 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
4971 if (!importFunc)
4972 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
4973 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
4974 pvAuxInfo, phKey);
4975 if (hFunc)
4976 CryptFreeOIDFunctionAddress(hFunc, 0);
4977 return ret;