push 5bc4839baba05cc4333240c25295b8dd6e351557
[wine/hacks.git] / dlls / crypt32 / encode.c
blob4d137cebc2f5f9dde60d17f2a7cef777863a50c3
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, PCRYPT_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 BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
132 DWORD bytesNeeded, significantBytes = 0;
134 if (len <= 0x7f)
135 bytesNeeded = 1;
136 else
138 DWORD temp;
140 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
141 temp <<= 8, significantBytes--)
143 bytesNeeded = significantBytes + 1;
145 if (!pbEncoded)
147 *pcbEncoded = bytesNeeded;
148 return TRUE;
150 if (*pcbEncoded < bytesNeeded)
152 SetLastError(ERROR_MORE_DATA);
153 return FALSE;
155 if (len <= 0x7f)
156 *pbEncoded = (BYTE)len;
157 else
159 DWORD i;
161 *pbEncoded++ = significantBytes | 0x80;
162 for (i = 0; i < significantBytes; i++)
164 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
165 len >>= 8;
168 *pcbEncoded = bytesNeeded;
169 return TRUE;
172 BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
173 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
174 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
176 BOOL ret;
177 DWORD i, dataLen = 0;
179 TRACE("%p, %d, %08x, %p, %p, %d\n", items, cItem, dwFlags, pEncodePara,
180 pbEncoded, *pcbEncoded);
181 for (i = 0, ret = TRUE; ret && i < cItem; i++)
183 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
184 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
185 NULL, &items[i].size);
186 /* Some functions propagate their errors through the size */
187 if (!ret)
188 *pcbEncoded = items[i].size;
189 dataLen += items[i].size;
191 if (ret)
193 DWORD lenBytes, bytesNeeded;
195 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
196 bytesNeeded = 1 + lenBytes + dataLen;
197 if (!pbEncoded)
198 *pcbEncoded = bytesNeeded;
199 else
201 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
202 pcbEncoded, bytesNeeded)))
204 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
205 pbEncoded = *(BYTE **)pbEncoded;
206 *pbEncoded++ = ASN_SEQUENCE;
207 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
208 pbEncoded += lenBytes;
209 for (i = 0; ret && i < cItem; i++)
211 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
212 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
213 NULL, pbEncoded, &items[i].size);
214 /* Some functions propagate their errors through the size */
215 if (!ret)
216 *pcbEncoded = items[i].size;
217 pbEncoded += items[i].size;
222 TRACE("returning %d (%08x)\n", ret, GetLastError());
223 return ret;
226 BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
227 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
228 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
230 BOOL ret;
231 const struct AsnConstructedItem *item = pvStructInfo;
232 DWORD len;
234 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
235 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
237 DWORD dataLen, bytesNeeded;
239 CRYPT_EncodeLen(len, NULL, &dataLen);
240 bytesNeeded = 1 + dataLen + len;
241 if (!pbEncoded)
242 *pcbEncoded = bytesNeeded;
243 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
244 pbEncoded, pcbEncoded, bytesNeeded)))
246 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
247 pbEncoded = *(BYTE **)pbEncoded;
248 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
249 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
250 pbEncoded += dataLen;
251 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
252 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
253 pbEncoded, &len);
254 if (!ret)
256 /* Some functions propagate their errors through the size */
257 *pcbEncoded = len;
261 else
263 /* Some functions propagate their errors through the size */
264 *pcbEncoded = len;
266 return ret;
269 struct AsnEncodeTagSwappedItem
271 BYTE tag;
272 const void *pvStructInfo;
273 CryptEncodeObjectExFunc encodeFunc;
276 /* Sort of a wacky hack, it encodes something using the struct
277 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
278 * given in the struct AsnEncodeTagSwappedItem.
280 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
281 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
282 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
284 BOOL ret;
285 const struct AsnEncodeTagSwappedItem *item = pvStructInfo;
287 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
288 item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
289 if (ret && pbEncoded)
290 *pbEncoded = item->tag;
291 return ret;
294 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
295 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
296 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
298 const DWORD *ver = pvStructInfo;
299 BOOL ret;
301 /* CERT_V1 is not encoded */
302 if (*ver == CERT_V1)
304 *pcbEncoded = 0;
305 ret = TRUE;
307 else
309 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
311 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
312 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
314 return ret;
317 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
318 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
319 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
321 const CRYPT_DER_BLOB *blob = pvStructInfo;
322 BOOL ret;
324 if (!pbEncoded)
326 *pcbEncoded = blob->cbData;
327 ret = TRUE;
329 else
331 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
332 pcbEncoded, blob->cbData)))
334 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
335 pbEncoded = *(BYTE **)pbEncoded;
336 if (blob->cbData)
337 memcpy(pbEncoded, blob->pbData, blob->cbData);
338 *pcbEncoded = blob->cbData;
339 ret = TRUE;
342 return ret;
345 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
346 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
347 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
349 BOOL ret;
350 /* This has two filetimes in a row, a NotBefore and a NotAfter */
351 const FILETIME *timePtr = pvStructInfo;
352 struct AsnEncodeSequenceItem items[] = {
353 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
354 { timePtr + 1, CRYPT_AsnEncodeChoiceOfTime, 0 },
357 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
358 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
359 pcbEncoded);
360 return ret;
363 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
364 * if they are empty.
366 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
367 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
368 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
369 DWORD *pcbEncoded)
371 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
372 static const BYTE asn1Null[] = { ASN_NULL, 0 };
373 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
374 (LPBYTE)asn1Null };
375 BOOL ret;
376 struct AsnEncodeSequenceItem items[2] = {
377 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
378 { NULL, CRYPT_CopyEncodedBlob, 0 },
381 if (algo->Parameters.cbData)
382 items[1].pvStructInfo = &algo->Parameters;
383 else
384 items[1].pvStructInfo = &nullBlob;
385 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
386 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
387 pcbEncoded);
388 return ret;
391 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType,
392 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
393 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
395 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
396 BOOL ret;
397 struct AsnEncodeSequenceItem items[] = {
398 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
399 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
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_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
409 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
410 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
412 BOOL ret;
414 __TRY
416 const CERT_PUBLIC_KEY_INFO *info = pvStructInfo;
417 struct AsnEncodeSequenceItem items[] = {
418 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
419 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
422 TRACE("Encoding public key with OID %s\n",
423 debugstr_a(info->Algorithm.pszObjId));
424 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
425 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
426 pcbEncoded);
428 __EXCEPT_PAGE_FAULT
430 SetLastError(STATUS_ACCESS_VIOLATION);
431 ret = FALSE;
433 __ENDTRY
434 return ret;
437 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
438 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
439 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
441 BOOL ret;
443 __TRY
445 const CERT_SIGNED_CONTENT_INFO *info = pvStructInfo;
446 struct AsnEncodeSequenceItem items[] = {
447 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
448 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
449 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
452 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
453 items[2].encodeFunc = CRYPT_AsnEncodeBits;
454 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
455 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
456 pcbEncoded);
458 __EXCEPT_PAGE_FAULT
460 SetLastError(STATUS_ACCESS_VIOLATION);
461 ret = FALSE;
463 __ENDTRY
464 return ret;
467 BOOL WINAPI CRYPT_AsnEncodePubKeyInfoNoNull(DWORD dwCertEncodingType,
468 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
469 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
471 BOOL ret;
472 const CERT_PUBLIC_KEY_INFO *info = pvStructInfo;
473 struct AsnEncodeSequenceItem items[] = {
474 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
475 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
478 TRACE("Encoding public key with OID %s\n",
479 debugstr_a(info->Algorithm.pszObjId));
480 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
481 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
482 pcbEncoded);
483 return ret;
486 /* Like in Windows, this blithely ignores the validity of the passed-in
487 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
488 * decode properly, see CRYPT_AsnDecodeCertInfo.
490 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
491 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
492 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
494 BOOL ret;
496 __TRY
498 const CERT_INFO *info = pvStructInfo;
499 struct AsnEncodeSequenceItem items[10] = {
500 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
501 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
502 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
503 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
504 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
505 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
506 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfoNoNull, 0 },
507 { 0 }
509 struct AsnConstructedItem constructed = { 0 };
510 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
511 DWORD cItem = 7, cSwapped = 0;
513 if (info->IssuerUniqueId.cbData)
515 swapped[cSwapped].tag = ASN_CONTEXT | 1;
516 swapped[cSwapped].pvStructInfo = &info->IssuerUniqueId;
517 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
518 items[cItem].pvStructInfo = &swapped[cSwapped];
519 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
520 cSwapped++;
521 cItem++;
523 if (info->SubjectUniqueId.cbData)
525 swapped[cSwapped].tag = ASN_CONTEXT | 2;
526 swapped[cSwapped].pvStructInfo = &info->SubjectUniqueId;
527 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
528 items[cItem].pvStructInfo = &swapped[cSwapped];
529 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
530 cSwapped++;
531 cItem++;
533 if (info->cExtension)
535 constructed.tag = 3;
536 constructed.pvStructInfo = &info->cExtension;
537 constructed.encodeFunc = CRYPT_AsnEncodeExtensions;
538 items[cItem].pvStructInfo = &constructed;
539 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
540 cItem++;
543 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
544 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
546 __EXCEPT_PAGE_FAULT
548 SetLastError(STATUS_ACCESS_VIOLATION);
549 ret = FALSE;
551 __ENDTRY
552 return ret;
555 static BOOL CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
556 BYTE *pbEncoded, DWORD *pcbEncoded)
558 struct AsnEncodeSequenceItem items[3] = {
559 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
560 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
561 { 0 }
563 DWORD cItem = 2;
564 BOOL ret;
566 TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded);
568 if (entry->cExtension)
570 items[cItem].pvStructInfo = &entry->cExtension;
571 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
572 cItem++;
575 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
576 pbEncoded, pcbEncoded);
578 TRACE("returning %d (%08x)\n", ret, GetLastError());
579 return ret;
582 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
583 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
584 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
586 DWORD bytesNeeded, dataLen, lenBytes, i;
587 const CRL_INFO *info = pvStructInfo;
588 const CRL_ENTRY *rgCRLEntry = info->rgCRLEntry;
589 BOOL ret = TRUE;
591 for (i = 0, dataLen = 0; ret && i < info->cCRLEntry; i++)
593 DWORD size;
595 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
596 if (ret)
597 dataLen += size;
599 if (ret)
601 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
602 bytesNeeded = 1 + lenBytes + dataLen;
603 if (!pbEncoded)
604 *pcbEncoded = bytesNeeded;
605 else
607 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
608 pcbEncoded, bytesNeeded)))
610 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
611 pbEncoded = *(BYTE **)pbEncoded;
612 *pbEncoded++ = ASN_SEQUENCEOF;
613 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
614 pbEncoded += lenBytes;
615 for (i = 0; i < info->cCRLEntry; i++)
617 DWORD size = dataLen;
619 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], pbEncoded,
620 &size);
621 pbEncoded += size;
622 dataLen -= size;
627 return ret;
630 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
631 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
632 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
634 const DWORD *ver = pvStructInfo;
635 BOOL ret;
637 /* CRL_V1 is not encoded */
638 if (*ver == CRL_V1)
640 *pcbEncoded = 0;
641 ret = TRUE;
643 else
644 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
645 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
646 return ret;
649 /* Like in Windows, this blithely ignores the validity of the passed-in
650 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
651 * decode properly, see CRYPT_AsnDecodeCRLInfo.
653 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
654 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
655 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
657 BOOL ret;
659 __TRY
661 const CRL_INFO *info = pvStructInfo;
662 struct AsnEncodeSequenceItem items[7] = {
663 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
664 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
665 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
666 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
667 { 0 }
669 struct AsnConstructedItem constructed[1] = { { 0 } };
670 DWORD cItem = 4, cConstructed = 0;
672 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
674 items[cItem].pvStructInfo = &info->NextUpdate;
675 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
676 cItem++;
678 if (info->cCRLEntry)
680 items[cItem].pvStructInfo = info;
681 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
682 cItem++;
684 if (info->cExtension)
686 constructed[cConstructed].tag = 0;
687 constructed[cConstructed].pvStructInfo = &info->cExtension;
688 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
689 items[cItem].pvStructInfo = &constructed[cConstructed];
690 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
691 cConstructed++;
692 cItem++;
695 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
696 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
698 __EXCEPT_PAGE_FAULT
700 SetLastError(STATUS_ACCESS_VIOLATION);
701 ret = FALSE;
703 __ENDTRY
704 return ret;
707 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
708 DWORD *pcbEncoded)
710 BOOL ret;
711 struct AsnEncodeSequenceItem items[3] = {
712 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
713 { NULL, NULL, 0 },
714 { NULL, NULL, 0 },
716 DWORD cItem = 1;
718 TRACE("%p, %p, %d\n", ext, pbEncoded, *pcbEncoded);
720 if (ext->fCritical)
722 items[cItem].pvStructInfo = &ext->fCritical;
723 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
724 cItem++;
726 items[cItem].pvStructInfo = &ext->Value;
727 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
728 cItem++;
730 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
731 pbEncoded, pcbEncoded);
732 TRACE("returning %d (%08x)\n", ret, GetLastError());
733 return ret;
736 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
737 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
738 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
740 BOOL ret;
742 __TRY
744 DWORD bytesNeeded, dataLen, lenBytes, i;
745 const CERT_EXTENSIONS *exts = pvStructInfo;
747 ret = TRUE;
748 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
750 DWORD size;
752 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
753 if (ret)
754 dataLen += size;
756 if (ret)
758 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
759 bytesNeeded = 1 + lenBytes + dataLen;
760 if (!pbEncoded)
761 *pcbEncoded = bytesNeeded;
762 else
764 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
765 pbEncoded, pcbEncoded, bytesNeeded)))
767 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
768 pbEncoded = *(BYTE **)pbEncoded;
769 *pbEncoded++ = ASN_SEQUENCEOF;
770 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
771 pbEncoded += lenBytes;
772 for (i = 0; i < exts->cExtension; i++)
774 DWORD size = dataLen;
776 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
777 pbEncoded, &size);
778 pbEncoded += size;
779 dataLen -= size;
785 __EXCEPT_PAGE_FAULT
787 SetLastError(STATUS_ACCESS_VIOLATION);
788 ret = FALSE;
790 __ENDTRY
791 return ret;
794 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
795 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
796 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
798 LPCSTR pszObjId = pvStructInfo;
799 DWORD bytesNeeded = 0, lenBytes;
800 BOOL ret = TRUE;
801 int firstPos = 0;
802 BYTE firstByte = 0;
804 TRACE("%s\n", debugstr_a(pszObjId));
806 if (pszObjId)
808 const char *ptr;
809 int val1, val2;
811 if (sscanf(pszObjId, "%d.%d%n", &val1, &val2, &firstPos) != 2)
813 SetLastError(CRYPT_E_ASN1_ERROR);
814 return FALSE;
816 bytesNeeded++;
817 firstByte = val1 * 40 + val2;
818 ptr = pszObjId + firstPos;
819 if (*ptr == '.')
821 ptr++;
822 firstPos++;
824 while (ret && *ptr)
826 int pos;
828 /* note I assume each component is at most 32-bits long in base 2 */
829 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
831 if (val1 >= 0x10000000)
832 bytesNeeded += 5;
833 else if (val1 >= 0x200000)
834 bytesNeeded += 4;
835 else if (val1 >= 0x4000)
836 bytesNeeded += 3;
837 else if (val1 >= 0x80)
838 bytesNeeded += 2;
839 else
840 bytesNeeded += 1;
841 ptr += pos;
842 if (*ptr == '.')
843 ptr++;
845 else
847 SetLastError(CRYPT_E_ASN1_ERROR);
848 return FALSE;
851 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
853 else
854 lenBytes = 1;
855 bytesNeeded += 1 + lenBytes;
856 if (pbEncoded)
858 if (*pcbEncoded < bytesNeeded)
860 SetLastError(ERROR_MORE_DATA);
861 ret = FALSE;
863 else
865 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
866 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
867 pbEncoded += lenBytes;
868 if (pszObjId)
870 const char *ptr;
871 int val, pos;
873 *pbEncoded++ = firstByte;
874 ptr = pszObjId + firstPos;
875 while (ret && *ptr)
877 sscanf(ptr, "%d%n", &val, &pos);
879 unsigned char outBytes[5];
880 int numBytes, i;
882 if (val >= 0x10000000)
883 numBytes = 5;
884 else if (val >= 0x200000)
885 numBytes = 4;
886 else if (val >= 0x4000)
887 numBytes = 3;
888 else if (val >= 0x80)
889 numBytes = 2;
890 else
891 numBytes = 1;
892 for (i = numBytes; i > 0; i--)
894 outBytes[i - 1] = val & 0x7f;
895 val >>= 7;
897 for (i = 0; i < numBytes - 1; i++)
898 *pbEncoded++ = outBytes[i] | 0x80;
899 *pbEncoded++ = outBytes[i];
900 ptr += pos;
901 if (*ptr == '.')
902 ptr++;
908 *pcbEncoded = bytesNeeded;
909 return ret;
912 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
913 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
914 DWORD *pcbEncoded)
916 BOOL ret = TRUE;
917 LPCSTR str = (LPCSTR)value->Value.pbData;
918 DWORD bytesNeeded, lenBytes, encodedLen;
920 encodedLen = value->Value.cbData ? value->Value.cbData : strlen(str);
921 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
922 bytesNeeded = 1 + lenBytes + encodedLen;
923 if (!pbEncoded)
924 *pcbEncoded = bytesNeeded;
925 else
927 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
928 pbEncoded, pcbEncoded, bytesNeeded)))
930 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
931 pbEncoded = *(BYTE **)pbEncoded;
932 *pbEncoded++ = tag;
933 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
934 pbEncoded += lenBytes;
935 memcpy(pbEncoded, str, encodedLen);
938 return ret;
941 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
942 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
943 DWORD *pcbEncoded)
945 BOOL ret = TRUE;
946 LPCWSTR str = (LPCWSTR)value->Value.pbData;
947 DWORD bytesNeeded, lenBytes, strLen;
949 if (value->Value.cbData)
950 strLen = value->Value.cbData / sizeof(WCHAR);
951 else if (value->Value.pbData)
952 strLen = lstrlenW(str);
953 else
954 strLen = 0;
955 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
956 bytesNeeded = 1 + lenBytes + strLen * 2;
957 if (!pbEncoded)
958 *pcbEncoded = bytesNeeded;
959 else
961 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
962 pbEncoded, pcbEncoded, bytesNeeded)))
964 DWORD i;
966 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
967 pbEncoded = *(BYTE **)pbEncoded;
968 *pbEncoded++ = ASN_BMPSTRING;
969 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
970 pbEncoded += lenBytes;
971 for (i = 0; i < strLen; i++)
973 *pbEncoded++ = (str[i] & 0xff00) >> 8;
974 *pbEncoded++ = str[i] & 0x00ff;
978 return ret;
981 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
982 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
983 DWORD *pcbEncoded)
985 BOOL ret = TRUE;
986 LPCWSTR str = (LPCWSTR)value->Value.pbData;
987 DWORD bytesNeeded, lenBytes, encodedLen, strLen;
989 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
990 strlenW(str);
991 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
992 NULL);
993 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
994 bytesNeeded = 1 + lenBytes + encodedLen;
995 if (!pbEncoded)
996 *pcbEncoded = bytesNeeded;
997 else
999 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1000 pbEncoded, pcbEncoded, bytesNeeded)))
1002 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1003 pbEncoded = *(BYTE **)pbEncoded;
1004 *pbEncoded++ = ASN_UTF8STRING;
1005 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1006 pbEncoded += lenBytes;
1007 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
1008 bytesNeeded - lenBytes - 1, NULL, NULL);
1011 return ret;
1014 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
1015 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1016 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1018 BOOL ret = TRUE;
1020 __TRY
1022 const CERT_NAME_VALUE *value = pvStructInfo;
1024 switch (value->dwValueType)
1026 case CERT_RDN_ANY_TYPE:
1027 /* explicitly disallowed */
1028 SetLastError(E_INVALIDARG);
1029 ret = FALSE;
1030 break;
1031 case CERT_RDN_ENCODED_BLOB:
1032 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
1033 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1034 break;
1035 case CERT_RDN_OCTET_STRING:
1036 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1037 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1038 break;
1039 case CERT_RDN_NUMERIC_STRING:
1040 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1041 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1042 break;
1043 case CERT_RDN_PRINTABLE_STRING:
1044 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1045 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1046 break;
1047 case CERT_RDN_TELETEX_STRING:
1048 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1049 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1050 break;
1051 case CERT_RDN_VIDEOTEX_STRING:
1052 ret = CRYPT_AsnEncodeStringCoerce(value,
1053 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1054 break;
1055 case CERT_RDN_IA5_STRING:
1056 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1057 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1058 break;
1059 case CERT_RDN_GRAPHIC_STRING:
1060 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1061 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1062 break;
1063 case CERT_RDN_VISIBLE_STRING:
1064 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1065 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1066 break;
1067 case CERT_RDN_GENERAL_STRING:
1068 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1069 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1070 break;
1071 case CERT_RDN_UNIVERSAL_STRING:
1072 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1073 SetLastError(CRYPT_E_ASN1_CHOICE);
1074 ret = FALSE;
1075 break;
1076 case CERT_RDN_BMP_STRING:
1077 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1078 pbEncoded, pcbEncoded);
1079 break;
1080 case CERT_RDN_UTF8_STRING:
1081 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1082 pbEncoded, pcbEncoded);
1083 break;
1084 default:
1085 SetLastError(CRYPT_E_ASN1_CHOICE);
1086 ret = FALSE;
1089 __EXCEPT_PAGE_FAULT
1091 SetLastError(STATUS_ACCESS_VIOLATION);
1092 ret = FALSE;
1094 __ENDTRY
1095 return ret;
1098 static BOOL CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1099 const CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1100 BYTE *pbEncoded, DWORD *pcbEncoded)
1102 DWORD bytesNeeded = 0, lenBytes, size;
1103 BOOL ret;
1105 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1106 0, NULL, NULL, &size);
1107 if (ret)
1109 bytesNeeded += size;
1110 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1111 * with dwValueType, so "cast" it to get its encoded size
1113 ret = nameValueEncodeFunc(dwCertEncodingType, NULL, &attr->dwValueType,
1114 0, NULL, NULL, &size);
1115 if (ret)
1117 bytesNeeded += size;
1118 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1119 bytesNeeded += 1 + lenBytes;
1120 if (pbEncoded)
1122 if (*pcbEncoded < bytesNeeded)
1124 SetLastError(ERROR_MORE_DATA);
1125 ret = FALSE;
1127 else
1129 *pbEncoded++ = ASN_SEQUENCE;
1130 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1131 &lenBytes);
1132 pbEncoded += lenBytes;
1133 size = bytesNeeded - 1 - lenBytes;
1134 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1135 attr->pszObjId, 0, NULL, pbEncoded, &size);
1136 if (ret)
1138 pbEncoded += size;
1139 size = bytesNeeded - 1 - lenBytes - size;
1140 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1141 &attr->dwValueType, 0, NULL, pbEncoded, &size);
1142 if (!ret)
1143 *pcbEncoded = size;
1147 if (ret)
1148 *pcbEncoded = bytesNeeded;
1150 else
1152 /* Have to propagate index of failing character */
1153 *pcbEncoded = size;
1156 return ret;
1159 static int BLOBComp(const void *l, const void *r)
1161 const CRYPT_DER_BLOB *a = l, *b = r;
1162 int ret;
1164 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1165 ret = a->cbData - b->cbData;
1166 return ret;
1169 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1171 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1172 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1173 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1175 const CRYPT_BLOB_ARRAY *set = pvStructInfo;
1176 DWORD bytesNeeded = 0, lenBytes, i;
1177 BOOL ret;
1179 for (i = 0; i < set->cBlob; i++)
1180 bytesNeeded += set->rgBlob[i].cbData;
1181 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1182 bytesNeeded += 1 + lenBytes;
1183 if (!pbEncoded)
1185 *pcbEncoded = bytesNeeded;
1186 ret = TRUE;
1188 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1189 pbEncoded, pcbEncoded, bytesNeeded)))
1191 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1192 pbEncoded = *(BYTE **)pbEncoded;
1193 qsort(set->rgBlob, set->cBlob, sizeof(CRYPT_DER_BLOB), BLOBComp);
1194 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1195 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1196 pbEncoded += lenBytes;
1197 for (i = 0; ret && i < set->cBlob; i++)
1199 memcpy(pbEncoded, set->rgBlob[i].pbData, set->rgBlob[i].cbData);
1200 pbEncoded += set->rgBlob[i].cbData;
1203 return ret;
1206 struct DERSetDescriptor
1208 DWORD cItems;
1209 const void *items;
1210 size_t itemSize;
1211 size_t itemOffset;
1212 CryptEncodeObjectExFunc encode;
1215 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,
1216 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1217 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1219 const struct DERSetDescriptor *desc = pvStructInfo;
1220 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1221 BOOL ret = TRUE;
1222 DWORD i;
1224 if (desc->cItems)
1226 setOf.rgBlob = CryptMemAlloc(desc->cItems * sizeof(CRYPT_DER_BLOB));
1227 if (!setOf.rgBlob)
1228 ret = FALSE;
1229 else
1231 setOf.cBlob = desc->cItems;
1232 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1235 for (i = 0; ret && i < setOf.cBlob; i++)
1237 ret = desc->encode(dwCertEncodingType, lpszStructType,
1238 (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
1239 0, NULL, NULL, &setOf.rgBlob[i].cbData);
1240 if (ret)
1242 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1243 if (!setOf.rgBlob[i].pbData)
1244 ret = FALSE;
1245 else
1246 ret = desc->encode(dwCertEncodingType, lpszStructType,
1247 (const BYTE *)desc->items + i * desc->itemSize +
1248 desc->itemOffset, 0, NULL, setOf.rgBlob[i].pbData,
1249 &setOf.rgBlob[i].cbData);
1251 /* Some functions propagate their errors through the size */
1252 if (!ret)
1253 *pcbEncoded = setOf.rgBlob[i].cbData;
1255 if (ret)
1257 DWORD bytesNeeded = 0, lenBytes;
1259 for (i = 0; i < setOf.cBlob; i++)
1260 bytesNeeded += setOf.rgBlob[i].cbData;
1261 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1262 bytesNeeded += 1 + lenBytes;
1263 if (!pbEncoded)
1264 *pcbEncoded = bytesNeeded;
1265 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1266 pbEncoded, pcbEncoded, bytesNeeded)))
1268 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1269 pbEncoded = *(BYTE **)pbEncoded;
1270 qsort(setOf.rgBlob, setOf.cBlob, sizeof(CRYPT_DER_BLOB),
1271 BLOBComp);
1272 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1273 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1274 pbEncoded += lenBytes;
1275 for (i = 0; i < setOf.cBlob; i++)
1277 memcpy(pbEncoded, setOf.rgBlob[i].pbData,
1278 setOf.rgBlob[i].cbData);
1279 pbEncoded += setOf.rgBlob[i].cbData;
1283 for (i = 0; i < setOf.cBlob; i++)
1284 CryptMemFree(setOf.rgBlob[i].pbData);
1285 CryptMemFree(setOf.rgBlob);
1286 return ret;
1289 static BOOL CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, const CERT_RDN *rdn,
1290 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1291 DWORD *pcbEncoded)
1293 BOOL ret;
1294 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1296 __TRY
1298 DWORD i;
1300 ret = TRUE;
1301 if (rdn->cRDNAttr)
1303 setOf.cBlob = rdn->cRDNAttr;
1304 setOf.rgBlob = CryptMemAlloc(rdn->cRDNAttr *
1305 sizeof(CRYPT_DER_BLOB));
1306 if (!setOf.rgBlob)
1307 ret = FALSE;
1308 else
1309 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1311 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1313 setOf.rgBlob[i].cbData = 0;
1314 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1315 nameValueEncodeFunc, NULL, &setOf.rgBlob[i].cbData);
1316 if (ret)
1318 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1319 if (!setOf.rgBlob[i].pbData)
1320 ret = FALSE;
1321 else
1322 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1323 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1324 setOf.rgBlob[i].pbData, &setOf.rgBlob[i].cbData);
1326 if (!ret)
1328 /* Have to propagate index of failing character */
1329 *pcbEncoded = setOf.rgBlob[i].cbData;
1332 if (ret)
1333 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1334 pbEncoded, pcbEncoded);
1335 for (i = 0; i < setOf.cBlob; i++)
1336 CryptMemFree(setOf.rgBlob[i].pbData);
1338 __EXCEPT_PAGE_FAULT
1340 SetLastError(STATUS_ACCESS_VIOLATION);
1341 ret = FALSE;
1343 __ENDTRY
1344 CryptMemFree(setOf.rgBlob);
1345 return ret;
1348 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1349 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1350 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1352 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1353 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1354 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1355 DWORD *pcbEncoded)
1357 const CERT_NAME_VALUE *value = pvStructInfo;
1358 BOOL ret;
1360 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1361 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1362 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1363 else
1364 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1365 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1366 return ret;
1369 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1370 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1371 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1373 BOOL ret = TRUE;
1375 __TRY
1377 const CERT_NAME_INFO *info = pvStructInfo;
1378 DWORD bytesNeeded = 0, lenBytes, size, i;
1380 TRACE("encoding name with %d RDNs\n", info->cRDN);
1381 ret = TRUE;
1382 for (i = 0; ret && i < info->cRDN; i++)
1384 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1385 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1386 if (ret)
1387 bytesNeeded += size;
1388 else
1389 *pcbEncoded = size;
1391 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1392 bytesNeeded += 1 + lenBytes;
1393 if (ret)
1395 if (!pbEncoded)
1396 *pcbEncoded = bytesNeeded;
1397 else
1399 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1400 pbEncoded, pcbEncoded, bytesNeeded)))
1402 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1403 pbEncoded = *(BYTE **)pbEncoded;
1404 *pbEncoded++ = ASN_SEQUENCEOF;
1405 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1406 &lenBytes);
1407 pbEncoded += lenBytes;
1408 for (i = 0; ret && i < info->cRDN; i++)
1410 size = bytesNeeded;
1411 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1412 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1413 pbEncoded, &size);
1414 if (ret)
1416 pbEncoded += size;
1417 bytesNeeded -= size;
1419 else
1420 *pcbEncoded = size;
1426 __EXCEPT_PAGE_FAULT
1428 SetLastError(STATUS_ACCESS_VIOLATION);
1429 ret = FALSE;
1431 __ENDTRY
1432 return ret;
1435 static BOOL WINAPI CRYPT_AsnEncodeCTLVersion(DWORD dwCertEncodingType,
1436 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1437 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1439 const DWORD *ver = pvStructInfo;
1440 BOOL ret;
1442 /* CTL_V1 is not encoded */
1443 if (*ver == CTL_V1)
1445 *pcbEncoded = 0;
1446 ret = TRUE;
1448 else
1449 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
1450 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1451 return ret;
1454 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
1455 * if they are empty and the OID is not empty (otherwise omits them.)
1457 static BOOL WINAPI CRYPT_AsnEncodeCTLSubjectAlgorithm(
1458 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1459 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1460 DWORD *pcbEncoded)
1462 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
1463 BOOL ret;
1464 struct AsnEncodeSequenceItem items[2] = {
1465 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
1467 DWORD cItem = 1;
1469 if (algo->pszObjId)
1471 static const BYTE asn1Null[] = { ASN_NULL, 0 };
1472 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
1473 (LPBYTE)asn1Null };
1475 if (algo->Parameters.cbData)
1476 items[cItem].pvStructInfo = &algo->Parameters;
1477 else
1478 items[cItem].pvStructInfo = &nullBlob;
1479 items[cItem].encodeFunc = CRYPT_CopyEncodedBlob;
1480 cItem++;
1482 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1483 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1484 return ret;
1487 static BOOL CRYPT_AsnEncodeCTLEntry(const CTL_ENTRY *entry,
1488 BYTE *pbEncoded, DWORD *pcbEncoded)
1490 struct AsnEncodeSequenceItem items[2] = {
1491 { &entry->SubjectIdentifier, CRYPT_AsnEncodeOctets, 0 },
1492 { &entry->cAttribute, CRYPT_AsnEncodePKCSAttributes, 0 },
1494 BOOL ret;
1496 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1497 sizeof(items) / sizeof(items[0]), 0, NULL, pbEncoded, pcbEncoded);
1498 return ret;
1501 struct CTLEntries
1503 DWORD cEntry;
1504 CTL_ENTRY *rgEntry;
1507 static BOOL WINAPI CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType,
1508 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1509 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1511 BOOL ret;
1512 DWORD bytesNeeded, dataLen, lenBytes, i;
1513 const struct CTLEntries *entries = pvStructInfo;
1515 ret = TRUE;
1516 for (i = 0, dataLen = 0; ret && i < entries->cEntry; i++)
1518 DWORD size;
1520 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i], NULL, &size);
1521 if (ret)
1522 dataLen += size;
1524 if (ret)
1526 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1527 bytesNeeded = 1 + lenBytes + dataLen;
1528 if (!pbEncoded)
1529 *pcbEncoded = bytesNeeded;
1530 else
1532 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1533 pbEncoded, pcbEncoded, bytesNeeded)))
1535 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1536 pbEncoded = *(BYTE **)pbEncoded;
1537 *pbEncoded++ = ASN_SEQUENCEOF;
1538 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1539 pbEncoded += lenBytes;
1540 for (i = 0; ret && i < entries->cEntry; i++)
1542 DWORD size = dataLen;
1544 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i],
1545 pbEncoded, &size);
1546 pbEncoded += size;
1547 dataLen -= size;
1552 return ret;
1555 static BOOL WINAPI CRYPT_AsnEncodeCTL(DWORD dwCertEncodingType,
1556 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1557 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1559 BOOL ret = FALSE;
1561 __TRY
1563 const CTL_INFO *info = pvStructInfo;
1564 struct AsnEncodeSequenceItem items[9] = {
1565 { &info->dwVersion, CRYPT_AsnEncodeCTLVersion, 0 },
1566 { &info->SubjectUsage, CRYPT_AsnEncodeEnhancedKeyUsage, 0 },
1568 struct AsnConstructedItem constructed = { 0 };
1569 DWORD cItem = 2;
1571 if (info->ListIdentifier.cbData)
1573 items[cItem].pvStructInfo = &info->ListIdentifier;
1574 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
1575 cItem++;
1577 if (info->SequenceNumber.cbData)
1579 items[cItem].pvStructInfo = &info->SequenceNumber;
1580 items[cItem].encodeFunc = CRYPT_AsnEncodeInteger;
1581 cItem++;
1583 items[cItem].pvStructInfo = &info->ThisUpdate;
1584 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1585 cItem++;
1586 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
1588 items[cItem].pvStructInfo = &info->NextUpdate;
1589 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1590 cItem++;
1592 items[cItem].pvStructInfo = &info->SubjectAlgorithm;
1593 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLSubjectAlgorithm;
1594 cItem++;
1595 if (info->cCTLEntry)
1597 items[cItem].pvStructInfo = &info->cCTLEntry;
1598 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLEntries;
1599 cItem++;
1601 if (info->cExtension)
1603 constructed.tag = 0;
1604 constructed.pvStructInfo = &info->cExtension;
1605 constructed.encodeFunc = CRYPT_AsnEncodeExtensions;
1606 items[cItem].pvStructInfo = &constructed;
1607 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1608 cItem++;
1610 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1611 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1613 __EXCEPT_PAGE_FAULT
1615 SetLastError(STATUS_ACCESS_VIOLATION);
1617 __ENDTRY
1618 return ret;
1621 static BOOL CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType,
1622 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1623 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1625 BOOL ret = FALSE;
1627 __TRY
1629 const CRYPT_SMIME_CAPABILITY *capability = pvStructInfo;
1631 if (!capability->pszObjId)
1632 SetLastError(E_INVALIDARG);
1633 else
1635 struct AsnEncodeSequenceItem items[] = {
1636 { capability->pszObjId, CRYPT_AsnEncodeOid, 0 },
1637 { &capability->Parameters, CRYPT_CopyEncodedBlob, 0 },
1640 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1641 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1642 pcbEncoded);
1645 __EXCEPT_PAGE_FAULT
1647 SetLastError(STATUS_ACCESS_VIOLATION);
1649 __ENDTRY
1650 return ret;
1653 static BOOL WINAPI CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType,
1654 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1655 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1657 BOOL ret = FALSE;
1659 __TRY
1661 DWORD bytesNeeded, dataLen, lenBytes, i;
1662 const CRYPT_SMIME_CAPABILITIES *capabilities = pvStructInfo;
1664 ret = TRUE;
1665 for (i = 0, dataLen = 0; ret && i < capabilities->cCapability; i++)
1667 DWORD size;
1669 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType, NULL,
1670 &capabilities->rgCapability[i], 0, NULL, NULL, &size);
1671 if (ret)
1672 dataLen += size;
1674 if (ret)
1676 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1677 bytesNeeded = 1 + lenBytes + dataLen;
1678 if (!pbEncoded)
1679 *pcbEncoded = bytesNeeded;
1680 else
1682 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1683 pbEncoded, pcbEncoded, bytesNeeded)))
1685 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1686 pbEncoded = *(BYTE **)pbEncoded;
1687 *pbEncoded++ = ASN_SEQUENCEOF;
1688 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1689 pbEncoded += lenBytes;
1690 for (i = 0; i < capabilities->cCapability; i++)
1692 DWORD size = dataLen;
1694 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType,
1695 NULL, &capabilities->rgCapability[i], 0, NULL,
1696 pbEncoded, &size);
1697 pbEncoded += size;
1698 dataLen -= size;
1704 __EXCEPT_PAGE_FAULT
1706 SetLastError(STATUS_ACCESS_VIOLATION);
1708 __ENDTRY
1709 return ret;
1712 static BOOL WINAPI CRYPT_AsnEncodeNoticeNumbers(DWORD dwCertEncodingType,
1713 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1714 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1716 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
1717 DWORD bytesNeeded, dataLen, lenBytes, i;
1718 BOOL ret = TRUE;
1720 for (i = 0, dataLen = 0; ret && i < noticeRef->cNoticeNumbers; i++)
1722 DWORD size;
1724 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
1725 &noticeRef->rgNoticeNumbers[i], 0, NULL, NULL, &size);
1726 if (ret)
1727 dataLen += size;
1729 if (ret)
1731 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1732 bytesNeeded = 1 + lenBytes + dataLen;
1733 if (!pbEncoded)
1734 *pcbEncoded = bytesNeeded;
1735 else
1737 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1738 pcbEncoded, bytesNeeded)))
1740 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1741 pbEncoded = *(BYTE **)pbEncoded;
1742 *pbEncoded++ = ASN_SEQUENCE;
1743 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1744 pbEncoded += lenBytes;
1745 for (i = 0; i < noticeRef->cNoticeNumbers; i++)
1747 DWORD size = dataLen;
1749 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
1750 &noticeRef->rgNoticeNumbers[i], 0, NULL, pbEncoded, &size);
1751 pbEncoded += size;
1752 dataLen -= size;
1757 return ret;
1760 static BOOL WINAPI CRYPT_AsnEncodeNoticeReference(DWORD dwCertEncodingType,
1761 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1762 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1764 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
1765 BOOL ret;
1766 CERT_NAME_VALUE orgValue = { CERT_RDN_IA5_STRING,
1767 { 0, (LPBYTE)noticeRef->pszOrganization } };
1768 struct AsnEncodeSequenceItem items[] = {
1769 { &orgValue, CRYPT_AsnEncodeNameValue, 0 },
1770 { noticeRef, CRYPT_AsnEncodeNoticeNumbers, 0 },
1773 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1774 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1775 pcbEncoded);
1776 return ret;
1779 static BOOL WINAPI CRYPT_AsnEncodePolicyQualifierUserNotice(
1780 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1781 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1782 DWORD *pcbEncoded)
1784 BOOL ret = FALSE;
1786 __TRY
1788 const CERT_POLICY_QUALIFIER_USER_NOTICE *notice = pvStructInfo;
1789 struct AsnEncodeSequenceItem items[2];
1790 CERT_NAME_VALUE displayTextValue;
1791 DWORD cItem = 0;
1793 ret = TRUE;
1794 if (notice->pNoticeReference)
1796 items[cItem].encodeFunc = CRYPT_AsnEncodeNoticeReference;
1797 items[cItem].pvStructInfo = notice->pNoticeReference;
1798 cItem++;
1800 if (notice->pszDisplayText)
1802 displayTextValue.dwValueType = CERT_RDN_BMP_STRING;
1803 displayTextValue.Value.cbData = 0;
1804 displayTextValue.Value.pbData = (LPBYTE)notice->pszDisplayText;
1805 items[cItem].encodeFunc = CRYPT_AsnEncodeNameValue;
1806 items[cItem].pvStructInfo = &displayTextValue;
1807 cItem++;
1809 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1810 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1812 __EXCEPT_PAGE_FAULT
1814 SetLastError(STATUS_ACCESS_VIOLATION);
1816 __ENDTRY
1817 return ret;
1820 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1821 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1822 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1824 BOOL ret = FALSE;
1826 __TRY
1828 const CRYPT_ATTRIBUTE *attr = pvStructInfo;
1830 if (!attr->pszObjId)
1831 SetLastError(E_INVALIDARG);
1832 else
1834 struct AsnEncodeSequenceItem items[2] = {
1835 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1836 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1839 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1840 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1841 pcbEncoded);
1844 __EXCEPT_PAGE_FAULT
1846 SetLastError(STATUS_ACCESS_VIOLATION);
1848 __ENDTRY
1849 return ret;
1852 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1853 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1854 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1856 BOOL ret = FALSE;
1858 __TRY
1860 const CRYPT_ATTRIBUTES *attributes = pvStructInfo;
1861 struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
1862 sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
1864 ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
1865 &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1867 __EXCEPT_PAGE_FAULT
1869 SetLastError(STATUS_ACCESS_VIOLATION);
1871 __ENDTRY
1872 return ret;
1875 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1876 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
1877 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1878 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1879 DWORD *pcbEncoded)
1881 const CRYPT_CONTENT_INFO *info = pvStructInfo;
1882 struct AsnEncodeSequenceItem items[2] = {
1883 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1884 { NULL, NULL, 0 },
1886 struct AsnConstructedItem constructed = { 0 };
1887 DWORD cItem = 1;
1889 if (info->Content.cbData)
1891 constructed.tag = 0;
1892 constructed.pvStructInfo = &info->Content;
1893 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1894 items[cItem].pvStructInfo = &constructed;
1895 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1896 cItem++;
1898 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1899 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1902 BOOL CRYPT_AsnEncodePKCSDigestedData(const CRYPT_DIGESTED_DATA *digestedData,
1903 void *pvData, DWORD *pcbData)
1905 struct AsnEncodeSequenceItem items[] = {
1906 { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1907 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
1908 0 },
1909 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1910 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1913 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1914 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
1917 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1918 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1919 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1921 BOOL ret = FALSE;
1923 __TRY
1925 const CRYPT_CONTENT_INFO *info = pvStructInfo;
1927 if (!info->pszObjId)
1928 SetLastError(E_INVALIDARG);
1929 else
1930 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
1931 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1932 pcbEncoded);
1934 __EXCEPT_PAGE_FAULT
1936 SetLastError(STATUS_ACCESS_VIOLATION);
1938 __ENDTRY
1939 return ret;
1942 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1943 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1944 DWORD *pcbEncoded)
1946 BOOL ret = TRUE;
1947 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1948 DWORD bytesNeeded, lenBytes, encodedLen;
1950 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1951 strlenW(str);
1952 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1953 bytesNeeded = 1 + lenBytes + encodedLen;
1954 if (!pbEncoded)
1955 *pcbEncoded = bytesNeeded;
1956 else
1958 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1959 pbEncoded, pcbEncoded, bytesNeeded)))
1961 DWORD i;
1963 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1964 pbEncoded = *(BYTE **)pbEncoded;
1965 *pbEncoded++ = tag;
1966 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1967 pbEncoded += lenBytes;
1968 for (i = 0; i < encodedLen; i++)
1969 *pbEncoded++ = (BYTE)str[i];
1972 return ret;
1975 static void CRYPT_FreeSpace(PCRYPT_ENCODE_PARA pEncodePara, LPVOID pv)
1977 if (pEncodePara && pEncodePara->pfnFree)
1978 pEncodePara->pfnFree(pv);
1979 else
1980 LocalFree(pv);
1983 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
1984 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1985 DWORD *pcbEncoded)
1987 BOOL ret = TRUE;
1988 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1989 DWORD bytesNeeded, lenBytes, encodedLen;
1991 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1992 strlenW(str);
1993 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1994 bytesNeeded = 1 + lenBytes + encodedLen;
1995 if (!pbEncoded)
1996 *pcbEncoded = bytesNeeded;
1997 else
1999 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2000 pbEncoded, pcbEncoded, bytesNeeded)))
2002 DWORD i;
2003 BYTE *ptr;
2005 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2006 ptr = *(BYTE **)pbEncoded;
2007 else
2008 ptr = pbEncoded;
2009 *ptr++ = ASN_NUMERICSTRING;
2010 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2011 ptr += lenBytes;
2012 for (i = 0; ret && i < encodedLen; i++)
2014 if (isdigitW(str[i]))
2015 *ptr++ = (BYTE)str[i];
2016 else
2018 *pcbEncoded = i;
2019 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
2020 ret = FALSE;
2023 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2024 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2027 return ret;
2030 static inline int isprintableW(WCHAR wc)
2032 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
2033 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
2034 wc == '/' || wc == ':' || wc == '=' || wc == '?';
2037 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
2038 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
2039 DWORD *pcbEncoded)
2041 BOOL ret = TRUE;
2042 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2043 DWORD bytesNeeded, lenBytes, encodedLen;
2045 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
2046 strlenW(str);
2047 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2048 bytesNeeded = 1 + lenBytes + encodedLen;
2049 if (!pbEncoded)
2050 *pcbEncoded = bytesNeeded;
2051 else
2053 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2054 pbEncoded, pcbEncoded, bytesNeeded)))
2056 DWORD i;
2057 BYTE *ptr;
2059 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2060 ptr = *(BYTE **)pbEncoded;
2061 else
2062 ptr = pbEncoded;
2063 *ptr++ = ASN_PRINTABLESTRING;
2064 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2065 ptr += lenBytes;
2066 for (i = 0; ret && i < encodedLen; i++)
2068 if (isprintableW(str[i]))
2069 *ptr++ = (BYTE)str[i];
2070 else
2072 *pcbEncoded = i;
2073 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
2074 ret = FALSE;
2077 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2078 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2081 return ret;
2084 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
2085 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
2086 DWORD *pcbEncoded)
2088 BOOL ret = TRUE;
2089 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2090 DWORD bytesNeeded, lenBytes, encodedLen;
2092 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
2093 strlenW(str);
2094 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2095 bytesNeeded = 1 + lenBytes + encodedLen;
2096 if (!pbEncoded)
2097 *pcbEncoded = bytesNeeded;
2098 else
2100 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2101 pbEncoded, pcbEncoded, bytesNeeded)))
2103 DWORD i;
2104 BYTE *ptr;
2106 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2107 ptr = *(BYTE **)pbEncoded;
2108 else
2109 ptr = pbEncoded;
2110 *ptr++ = ASN_IA5STRING;
2111 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2112 ptr += lenBytes;
2113 for (i = 0; ret && i < encodedLen; i++)
2115 if (str[i] <= 0x7f)
2116 *ptr++ = (BYTE)str[i];
2117 else
2119 *pcbEncoded = i;
2120 SetLastError(CRYPT_E_INVALID_IA5_STRING);
2121 ret = FALSE;
2124 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2125 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2128 return ret;
2131 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
2132 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
2133 DWORD *pcbEncoded)
2135 BOOL ret = TRUE;
2136 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2137 DWORD bytesNeeded, lenBytes, strLen;
2139 /* FIXME: doesn't handle composite characters */
2140 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
2141 strlenW(str);
2142 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
2143 bytesNeeded = 1 + lenBytes + strLen * 4;
2144 if (!pbEncoded)
2145 *pcbEncoded = bytesNeeded;
2146 else
2148 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2149 pbEncoded, pcbEncoded, bytesNeeded)))
2151 DWORD i;
2153 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2154 pbEncoded = *(BYTE **)pbEncoded;
2155 *pbEncoded++ = ASN_UNIVERSALSTRING;
2156 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
2157 pbEncoded += lenBytes;
2158 for (i = 0; i < strLen; i++)
2160 *pbEncoded++ = 0;
2161 *pbEncoded++ = 0;
2162 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
2163 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
2167 return ret;
2170 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
2171 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2172 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2174 BOOL ret = FALSE;
2176 __TRY
2178 const CERT_NAME_VALUE *value = pvStructInfo;
2180 switch (value->dwValueType)
2182 case CERT_RDN_ANY_TYPE:
2183 case CERT_RDN_ENCODED_BLOB:
2184 case CERT_RDN_OCTET_STRING:
2185 SetLastError(CRYPT_E_NOT_CHAR_STRING);
2186 break;
2187 case CERT_RDN_NUMERIC_STRING:
2188 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
2189 pbEncoded, pcbEncoded);
2190 break;
2191 case CERT_RDN_PRINTABLE_STRING:
2192 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
2193 pbEncoded, pcbEncoded);
2194 break;
2195 case CERT_RDN_TELETEX_STRING:
2196 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
2197 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2198 break;
2199 case CERT_RDN_VIDEOTEX_STRING:
2200 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
2201 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2202 break;
2203 case CERT_RDN_IA5_STRING:
2204 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
2205 pbEncoded, pcbEncoded);
2206 break;
2207 case CERT_RDN_GRAPHIC_STRING:
2208 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
2209 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2210 break;
2211 case CERT_RDN_VISIBLE_STRING:
2212 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
2213 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2214 break;
2215 case CERT_RDN_GENERAL_STRING:
2216 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
2217 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2218 break;
2219 case CERT_RDN_UNIVERSAL_STRING:
2220 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
2221 pbEncoded, pcbEncoded);
2222 break;
2223 case CERT_RDN_BMP_STRING:
2224 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
2225 pbEncoded, pcbEncoded);
2226 break;
2227 case CERT_RDN_UTF8_STRING:
2228 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
2229 pbEncoded, pcbEncoded);
2230 break;
2231 default:
2232 SetLastError(CRYPT_E_ASN1_CHOICE);
2235 __EXCEPT_PAGE_FAULT
2237 SetLastError(STATUS_ACCESS_VIOLATION);
2239 __ENDTRY
2240 return ret;
2243 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
2244 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2245 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2247 BOOL ret;
2249 __TRY
2251 const CERT_NAME_INFO *info = pvStructInfo;
2252 DWORD bytesNeeded = 0, lenBytes, size, i;
2254 TRACE("encoding name with %d RDNs\n", info->cRDN);
2255 ret = TRUE;
2256 for (i = 0; ret && i < info->cRDN; i++)
2258 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
2259 CRYPT_AsnEncodeNameValue, NULL, &size);
2260 if (ret)
2261 bytesNeeded += size;
2263 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2264 bytesNeeded += 1 + lenBytes;
2265 if (ret)
2267 if (!pbEncoded)
2268 *pcbEncoded = bytesNeeded;
2269 else
2271 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2272 pbEncoded, pcbEncoded, bytesNeeded)))
2274 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2275 pbEncoded = *(BYTE **)pbEncoded;
2276 *pbEncoded++ = ASN_SEQUENCEOF;
2277 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
2278 &lenBytes);
2279 pbEncoded += lenBytes;
2280 for (i = 0; ret && i < info->cRDN; i++)
2282 size = bytesNeeded;
2283 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
2284 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, pbEncoded,
2285 &size);
2286 if (ret)
2288 pbEncoded += size;
2289 bytesNeeded -= size;
2296 __EXCEPT_PAGE_FAULT
2298 SetLastError(STATUS_ACCESS_VIOLATION);
2299 ret = FALSE;
2301 __ENDTRY
2302 return ret;
2305 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
2306 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2307 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2309 BOOL val = *(const BOOL *)pvStructInfo, ret;
2311 TRACE("%d\n", val);
2313 if (!pbEncoded)
2315 *pcbEncoded = 3;
2316 ret = TRUE;
2318 else if (*pcbEncoded < 3)
2320 *pcbEncoded = 3;
2321 SetLastError(ERROR_MORE_DATA);
2322 ret = FALSE;
2324 else
2326 *pcbEncoded = 3;
2327 *pbEncoded++ = ASN_BOOL;
2328 *pbEncoded++ = 1;
2329 *pbEncoded++ = val ? 0xff : 0;
2330 ret = TRUE;
2332 TRACE("returning %d (%08x)\n", ret, GetLastError());
2333 return ret;
2336 static BOOL WINAPI CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType,
2337 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2338 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2340 const CERT_ALT_NAME_ENTRY *entry = pvStructInfo;
2341 BOOL ret;
2342 DWORD dataLen;
2343 BYTE tag;
2345 ret = TRUE;
2346 switch (entry->dwAltNameChoice)
2348 case CERT_ALT_NAME_RFC822_NAME:
2349 case CERT_ALT_NAME_DNS_NAME:
2350 case CERT_ALT_NAME_URL:
2351 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2352 if (entry->u.pwszURL)
2354 DWORD i;
2356 /* Not + 1: don't encode the NULL-terminator */
2357 dataLen = lstrlenW(entry->u.pwszURL);
2358 for (i = 0; ret && i < dataLen; i++)
2360 if (entry->u.pwszURL[i] > 0x7f)
2362 SetLastError(CRYPT_E_INVALID_IA5_STRING);
2363 ret = FALSE;
2364 *pcbEncoded = i;
2368 else
2369 dataLen = 0;
2370 break;
2371 case CERT_ALT_NAME_DIRECTORY_NAME:
2372 tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1);
2373 dataLen = entry->u.DirectoryName.cbData;
2374 break;
2375 case CERT_ALT_NAME_IP_ADDRESS:
2376 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2377 dataLen = entry->u.IPAddress.cbData;
2378 break;
2379 case CERT_ALT_NAME_REGISTERED_ID:
2381 struct AsnEncodeTagSwappedItem swapped =
2382 { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID,
2383 CRYPT_AsnEncodeOid };
2385 return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded,
2386 pcbEncoded);
2388 case CERT_ALT_NAME_OTHER_NAME:
2389 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
2390 return FALSE;
2391 default:
2392 SetLastError(E_INVALIDARG);
2393 return FALSE;
2395 if (ret)
2397 DWORD bytesNeeded, lenBytes;
2399 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2400 bytesNeeded = 1 + dataLen + lenBytes;
2401 if (!pbEncoded)
2402 *pcbEncoded = bytesNeeded;
2403 else if (*pcbEncoded < bytesNeeded)
2405 SetLastError(ERROR_MORE_DATA);
2406 *pcbEncoded = bytesNeeded;
2407 ret = FALSE;
2409 else
2411 *pbEncoded++ = tag;
2412 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2413 pbEncoded += lenBytes;
2414 switch (entry->dwAltNameChoice)
2416 case CERT_ALT_NAME_RFC822_NAME:
2417 case CERT_ALT_NAME_DNS_NAME:
2418 case CERT_ALT_NAME_URL:
2420 DWORD i;
2422 for (i = 0; i < dataLen; i++)
2423 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
2424 break;
2426 case CERT_ALT_NAME_DIRECTORY_NAME:
2427 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen);
2428 break;
2429 case CERT_ALT_NAME_IP_ADDRESS:
2430 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
2431 break;
2433 if (ret)
2434 *pcbEncoded = bytesNeeded;
2437 TRACE("returning %d (%08x)\n", ret, GetLastError());
2438 return ret;
2441 static BOOL WINAPI CRYPT_AsnEncodeIntegerSwapBytes(DWORD dwCertEncodingType,
2442 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2443 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2445 BOOL ret;
2447 __TRY
2449 const CRYPT_DATA_BLOB *blob = pvStructInfo;
2450 CRYPT_DATA_BLOB newBlob = { blob->cbData, NULL };
2452 ret = TRUE;
2453 if (newBlob.cbData)
2455 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2456 if (newBlob.pbData)
2458 DWORD i;
2460 for (i = 0; i < newBlob.cbData; i++)
2461 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2463 else
2464 ret = FALSE;
2466 if (ret)
2467 ret = CRYPT_AsnEncodeInteger(dwCertEncodingType, lpszStructType,
2468 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2469 CryptMemFree(newBlob.pbData);
2471 __EXCEPT_PAGE_FAULT
2473 SetLastError(STATUS_ACCESS_VIOLATION);
2474 ret = FALSE;
2476 __ENDTRY
2477 return ret;
2480 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
2481 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2482 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2484 BOOL ret;
2486 __TRY
2488 const CERT_AUTHORITY_KEY_ID_INFO *info = pvStructInfo;
2489 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2490 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2491 struct AsnConstructedItem constructed = { 0 };
2492 DWORD cItem = 0, cSwapped = 0;
2494 if (info->KeyId.cbData)
2496 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2497 swapped[cSwapped].pvStructInfo = &info->KeyId;
2498 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2499 items[cItem].pvStructInfo = &swapped[cSwapped];
2500 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2501 cSwapped++;
2502 cItem++;
2504 if (info->CertIssuer.cbData)
2506 constructed.tag = 1;
2507 constructed.pvStructInfo = &info->CertIssuer;
2508 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2509 items[cItem].pvStructInfo = &constructed;
2510 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2511 cItem++;
2513 if (info->CertSerialNumber.cbData)
2515 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2516 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2517 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2518 items[cItem].pvStructInfo = &swapped[cSwapped];
2519 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2520 cSwapped++;
2521 cItem++;
2523 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2524 pEncodePara, pbEncoded, pcbEncoded);
2526 __EXCEPT_PAGE_FAULT
2528 SetLastError(STATUS_ACCESS_VIOLATION);
2529 ret = FALSE;
2531 __ENDTRY
2532 return ret;
2535 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2536 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2537 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2539 BOOL ret;
2541 __TRY
2543 const CERT_ALT_NAME_INFO *info = pvStructInfo;
2544 DWORD bytesNeeded, dataLen, lenBytes, i;
2546 ret = TRUE;
2547 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2548 * can't encode an erroneous entry index if it's bigger than this.
2550 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2552 DWORD len;
2554 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, NULL,
2555 &info->rgAltEntry[i], 0, NULL, NULL, &len);
2556 if (ret)
2557 dataLen += len;
2558 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2560 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2561 * the bad character, now set the index of the bad
2562 * entry
2564 *pcbEncoded = (BYTE)i <<
2565 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2568 if (ret)
2570 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2571 bytesNeeded = 1 + lenBytes + dataLen;
2572 if (!pbEncoded)
2574 *pcbEncoded = bytesNeeded;
2575 ret = TRUE;
2577 else
2579 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2580 pbEncoded, pcbEncoded, bytesNeeded)))
2582 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2583 pbEncoded = *(BYTE **)pbEncoded;
2584 *pbEncoded++ = ASN_SEQUENCEOF;
2585 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2586 pbEncoded += lenBytes;
2587 for (i = 0; ret && i < info->cAltEntry; i++)
2589 DWORD len = dataLen;
2591 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType,
2592 NULL, &info->rgAltEntry[i], 0, NULL, pbEncoded, &len);
2593 if (ret)
2595 pbEncoded += len;
2596 dataLen -= len;
2603 __EXCEPT_PAGE_FAULT
2605 SetLastError(STATUS_ACCESS_VIOLATION);
2606 ret = FALSE;
2608 __ENDTRY
2609 return ret;
2612 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2613 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2614 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2616 BOOL ret;
2618 __TRY
2620 const CERT_AUTHORITY_KEY_ID2_INFO *info = pvStructInfo;
2621 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2622 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2623 DWORD cItem = 0, cSwapped = 0;
2625 if (info->KeyId.cbData)
2627 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2628 swapped[cSwapped].pvStructInfo = &info->KeyId;
2629 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2630 items[cItem].pvStructInfo = &swapped[cSwapped];
2631 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2632 cSwapped++;
2633 cItem++;
2635 if (info->AuthorityCertIssuer.cAltEntry)
2637 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2638 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2639 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2640 items[cItem].pvStructInfo = &swapped[cSwapped];
2641 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2642 cSwapped++;
2643 cItem++;
2645 if (info->AuthorityCertSerialNumber.cbData)
2647 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2648 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2649 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2650 items[cItem].pvStructInfo = &swapped[cSwapped];
2651 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2652 cSwapped++;
2653 cItem++;
2655 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2656 pEncodePara, pbEncoded, pcbEncoded);
2658 __EXCEPT_PAGE_FAULT
2660 SetLastError(STATUS_ACCESS_VIOLATION);
2661 ret = FALSE;
2663 __ENDTRY
2664 return ret;
2667 static BOOL CRYPT_AsnEncodeAccessDescription(
2668 const CERT_ACCESS_DESCRIPTION *descr, BYTE *pbEncoded, DWORD *pcbEncoded)
2670 struct AsnEncodeSequenceItem items[] = {
2671 { descr->pszAccessMethod, CRYPT_AsnEncodeOid, 0 },
2672 { &descr->AccessLocation, CRYPT_AsnEncodeAltNameEntry, 0 },
2675 if (!descr->pszAccessMethod)
2677 SetLastError(E_INVALIDARG);
2678 return FALSE;
2680 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
2681 sizeof(items) / sizeof(items[0]), 0, NULL, pbEncoded, pcbEncoded);
2684 static BOOL WINAPI CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType,
2685 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2686 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2688 BOOL ret;
2690 __TRY
2692 DWORD bytesNeeded, dataLen, lenBytes, i;
2693 const CERT_AUTHORITY_INFO_ACCESS *info = pvStructInfo;
2695 ret = TRUE;
2696 for (i = 0, dataLen = 0; ret && i < info->cAccDescr; i++)
2698 DWORD size;
2700 ret = CRYPT_AsnEncodeAccessDescription(&info->rgAccDescr[i], NULL,
2701 &size);
2702 if (ret)
2703 dataLen += size;
2705 if (ret)
2707 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2708 bytesNeeded = 1 + lenBytes + dataLen;
2709 if (!pbEncoded)
2710 *pcbEncoded = bytesNeeded;
2711 else
2713 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2714 pbEncoded, pcbEncoded, bytesNeeded)))
2716 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2717 pbEncoded = *(BYTE **)pbEncoded;
2718 *pbEncoded++ = ASN_SEQUENCEOF;
2719 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2720 pbEncoded += lenBytes;
2721 for (i = 0; i < info->cAccDescr; i++)
2723 DWORD size = dataLen;
2725 ret = CRYPT_AsnEncodeAccessDescription(
2726 &info->rgAccDescr[i], pbEncoded, &size);
2727 pbEncoded += size;
2728 dataLen -= size;
2734 __EXCEPT_PAGE_FAULT
2736 SetLastError(STATUS_ACCESS_VIOLATION);
2737 ret = FALSE;
2739 __ENDTRY
2740 return ret;
2743 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2744 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2745 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2747 BOOL ret;
2749 __TRY
2751 const CERT_BASIC_CONSTRAINTS_INFO *info = pvStructInfo;
2752 struct AsnEncodeSequenceItem items[3] = {
2753 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2754 { 0 }
2756 DWORD cItem = 1;
2758 if (info->fPathLenConstraint)
2760 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2761 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2762 cItem++;
2764 if (info->cSubtreesConstraint)
2766 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2767 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2768 cItem++;
2770 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2771 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2773 __EXCEPT_PAGE_FAULT
2775 SetLastError(STATUS_ACCESS_VIOLATION);
2776 ret = FALSE;
2778 __ENDTRY
2779 return ret;
2782 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2783 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2784 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2786 BOOL ret;
2788 __TRY
2790 const CERT_BASIC_CONSTRAINTS2_INFO *info = pvStructInfo;
2791 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2792 DWORD cItem = 0;
2794 if (info->fCA)
2796 items[cItem].pvStructInfo = &info->fCA;
2797 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2798 cItem++;
2800 if (info->fPathLenConstraint)
2802 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2803 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
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_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType,
2819 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2820 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2822 const CERT_POLICY_INFO *info = pvStructInfo;
2823 BOOL ret;
2825 if (!info->cPolicyQualifier)
2827 *pcbEncoded = 0;
2828 ret = TRUE;
2830 else
2832 struct AsnEncodeSequenceItem items[2] = {
2833 { NULL, CRYPT_AsnEncodeOid, 0 },
2834 { NULL, CRYPT_CopyEncodedBlob, 0 },
2836 DWORD bytesNeeded = 0, lenBytes, size, i;
2838 ret = TRUE;
2839 for (i = 0; ret && i < info->cPolicyQualifier; i++)
2841 items[0].pvStructInfo =
2842 info->rgPolicyQualifier[i].pszPolicyQualifierId;
2843 items[1].pvStructInfo = &info->rgPolicyQualifier[i].Qualifier;
2844 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2845 sizeof(items) / sizeof(items[0]),
2846 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
2847 if (ret)
2848 bytesNeeded += size;
2850 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2851 bytesNeeded += 1 + lenBytes;
2852 if (ret)
2854 if (!pbEncoded)
2855 *pcbEncoded = bytesNeeded;
2856 else
2858 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2859 pbEncoded, pcbEncoded, bytesNeeded)))
2861 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2862 pbEncoded = *(BYTE **)pbEncoded;
2863 *pbEncoded++ = ASN_SEQUENCEOF;
2864 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
2865 &lenBytes);
2866 pbEncoded += lenBytes;
2867 for (i = 0; ret && i < info->cPolicyQualifier; i++)
2869 items[0].pvStructInfo =
2870 info->rgPolicyQualifier[i].pszPolicyQualifierId;
2871 items[1].pvStructInfo =
2872 &info->rgPolicyQualifier[i].Qualifier;
2873 size = bytesNeeded;
2874 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2875 sizeof(items) / sizeof(items[0]),
2876 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
2877 &size);
2878 if (ret)
2880 pbEncoded += size;
2881 bytesNeeded -= size;
2888 return ret;
2891 static BOOL CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType,
2892 const CERT_POLICY_INFO *info, DWORD dwFlags, BYTE *pbEncoded,
2893 DWORD *pcbEncoded)
2895 struct AsnEncodeSequenceItem items[2] = {
2896 { info->pszPolicyIdentifier, CRYPT_AsnEncodeOid, 0 },
2897 { info, CRYPT_AsnEncodeCertPolicyQualifiers, 0 },
2899 BOOL ret;
2901 if (!info->pszPolicyIdentifier)
2903 SetLastError(E_INVALIDARG);
2904 return FALSE;
2906 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2907 sizeof(items) / sizeof(items[0]), dwFlags, NULL, pbEncoded, pcbEncoded);
2908 return ret;
2911 static BOOL WINAPI CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType,
2912 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2913 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2915 BOOL ret = FALSE;
2917 __TRY
2919 const CERT_POLICIES_INFO *info = pvStructInfo;
2920 DWORD bytesNeeded = 0, lenBytes, size, i;
2922 ret = TRUE;
2923 for (i = 0; ret && i < info->cPolicyInfo; i++)
2925 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
2926 &info->rgPolicyInfo[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
2927 &size);
2928 if (ret)
2929 bytesNeeded += size;
2931 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2932 bytesNeeded += 1 + lenBytes;
2933 if (ret)
2935 if (!pbEncoded)
2936 *pcbEncoded = bytesNeeded;
2937 else
2939 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2940 pbEncoded, pcbEncoded, bytesNeeded)))
2942 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2943 pbEncoded = *(BYTE **)pbEncoded;
2944 *pbEncoded++ = ASN_SEQUENCEOF;
2945 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
2946 &lenBytes);
2947 pbEncoded += lenBytes;
2948 for (i = 0; ret && i < info->cPolicyInfo; i++)
2950 size = bytesNeeded;
2951 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
2952 &info->rgPolicyInfo[i],
2953 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pbEncoded, &size);
2954 if (ret)
2956 pbEncoded += size;
2957 bytesNeeded -= size;
2964 __EXCEPT_PAGE_FAULT
2966 SetLastError(STATUS_ACCESS_VIOLATION);
2968 __ENDTRY
2969 return ret;
2972 static BOOL CRYPT_AsnEncodeCertPolicyMapping(DWORD dwCertEncodingType,
2973 const CERT_POLICY_MAPPING *mapping, DWORD dwFlags, BYTE *pbEncoded,
2974 DWORD *pcbEncoded)
2976 struct AsnEncodeSequenceItem items[] = {
2977 { mapping->pszIssuerDomainPolicy, CRYPT_AsnEncodeOid, 0 },
2978 { mapping->pszSubjectDomainPolicy, CRYPT_AsnEncodeOid, 0 },
2981 if (!mapping->pszIssuerDomainPolicy || !mapping->pszSubjectDomainPolicy)
2983 SetLastError(E_INVALIDARG);
2984 return FALSE;
2986 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2987 sizeof(items) / sizeof(items[0]), dwFlags, NULL, pbEncoded, pcbEncoded);
2990 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyMappings(DWORD dwCertEncodingType,
2991 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2992 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2994 BOOL ret = FALSE;
2996 __TRY
2998 const CERT_POLICY_MAPPINGS_INFO *info = pvStructInfo;
2999 DWORD bytesNeeded = 0, lenBytes, size, i;
3001 ret = TRUE;
3002 for (i = 0; ret && i < info->cPolicyMapping; i++)
3004 ret = CRYPT_AsnEncodeCertPolicyMapping(dwCertEncodingType,
3005 &info->rgPolicyMapping[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
3006 NULL, &size);
3007 if (ret)
3008 bytesNeeded += size;
3010 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3011 bytesNeeded += 1 + lenBytes;
3012 if (ret)
3014 if (!pbEncoded)
3015 *pcbEncoded = bytesNeeded;
3016 else
3018 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3019 pbEncoded, pcbEncoded, bytesNeeded)))
3021 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3022 pbEncoded = *(BYTE **)pbEncoded;
3023 *pbEncoded++ = ASN_SEQUENCEOF;
3024 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
3025 &lenBytes);
3026 pbEncoded += lenBytes;
3027 for (i = 0; ret && i < info->cPolicyMapping; i++)
3029 size = bytesNeeded;
3030 ret = CRYPT_AsnEncodeCertPolicyMapping(
3031 dwCertEncodingType, &info->rgPolicyMapping[i],
3032 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pbEncoded, &size);
3033 if (ret)
3035 pbEncoded += size;
3036 bytesNeeded -= size;
3043 __EXCEPT_PAGE_FAULT
3045 SetLastError(STATUS_ACCESS_VIOLATION);
3047 __ENDTRY
3048 return ret;
3051 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyConstraints(
3052 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3053 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3054 DWORD *pcbEncoded)
3056 BOOL ret = FALSE;
3058 __TRY
3060 const CERT_POLICY_CONSTRAINTS_INFO *info = pvStructInfo;
3061 struct AsnEncodeSequenceItem items[2];
3062 struct AsnEncodeTagSwappedItem swapped[2];
3063 DWORD cItem = 0, cSwapped = 0;
3065 if (info->fRequireExplicitPolicy)
3067 swapped[cSwapped].tag = ASN_CONTEXT | 0;
3068 swapped[cSwapped].pvStructInfo =
3069 &info->dwRequireExplicitPolicySkipCerts;
3070 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3071 items[cItem].pvStructInfo = &swapped[cSwapped];
3072 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3073 cSwapped++;
3074 cItem++;
3076 if (info->fInhibitPolicyMapping)
3078 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3079 swapped[cSwapped].pvStructInfo =
3080 &info->dwInhibitPolicyMappingSkipCerts;
3081 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3082 items[cItem].pvStructInfo = &swapped[cSwapped];
3083 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3084 cSwapped++;
3085 cItem++;
3087 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3088 dwFlags, NULL, pbEncoded, pcbEncoded);
3090 __EXCEPT_PAGE_FAULT
3092 SetLastError(STATUS_ACCESS_VIOLATION);
3094 __ENDTRY
3095 return ret;
3098 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
3099 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3100 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3102 BOOL ret;
3104 __TRY
3106 const BLOBHEADER *hdr = pvStructInfo;
3108 if (hdr->bType != PUBLICKEYBLOB)
3110 SetLastError(E_INVALIDARG);
3111 ret = FALSE;
3113 else
3115 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
3116 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
3117 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
3118 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
3119 struct AsnEncodeSequenceItem items[] = {
3120 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
3121 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
3124 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3125 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3126 pcbEncoded);
3129 __EXCEPT_PAGE_FAULT
3131 SetLastError(STATUS_ACCESS_VIOLATION);
3132 ret = FALSE;
3134 __ENDTRY
3135 return ret;
3138 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
3139 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3140 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3142 BOOL ret;
3144 __TRY
3146 const CRYPT_DATA_BLOB *blob = pvStructInfo;
3147 DWORD bytesNeeded, lenBytes;
3149 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
3150 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
3152 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
3153 bytesNeeded = 1 + lenBytes + blob->cbData;
3154 if (!pbEncoded)
3156 *pcbEncoded = bytesNeeded;
3157 ret = TRUE;
3159 else
3161 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3162 pcbEncoded, bytesNeeded)))
3164 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3165 pbEncoded = *(BYTE **)pbEncoded;
3166 *pbEncoded++ = ASN_OCTETSTRING;
3167 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
3168 pbEncoded += lenBytes;
3169 if (blob->cbData)
3170 memcpy(pbEncoded, blob->pbData, blob->cbData);
3174 __EXCEPT_PAGE_FAULT
3176 SetLastError(STATUS_ACCESS_VIOLATION);
3177 ret = FALSE;
3179 __ENDTRY
3180 TRACE("returning %d (%08x)\n", ret, GetLastError());
3181 return ret;
3184 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
3185 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3186 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3188 BOOL ret;
3190 __TRY
3192 const CRYPT_BIT_BLOB *blob = pvStructInfo;
3193 DWORD bytesNeeded, lenBytes, dataBytes;
3194 BYTE unusedBits;
3196 /* yep, MS allows cUnusedBits to be >= 8 */
3197 if (!blob->cUnusedBits)
3199 dataBytes = blob->cbData;
3200 unusedBits = 0;
3202 else if (blob->cbData * 8 > blob->cUnusedBits)
3204 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
3205 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
3206 blob->cUnusedBits;
3208 else
3210 dataBytes = 0;
3211 unusedBits = 0;
3213 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
3214 bytesNeeded = 1 + lenBytes + dataBytes + 1;
3215 if (!pbEncoded)
3217 *pcbEncoded = bytesNeeded;
3218 ret = TRUE;
3220 else
3222 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3223 pcbEncoded, bytesNeeded)))
3225 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3226 pbEncoded = *(BYTE **)pbEncoded;
3227 *pbEncoded++ = ASN_BITSTRING;
3228 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
3229 pbEncoded += lenBytes;
3230 *pbEncoded++ = unusedBits;
3231 if (dataBytes)
3233 BYTE mask = 0xff << unusedBits;
3235 if (dataBytes > 1)
3237 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
3238 pbEncoded += dataBytes - 1;
3240 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
3245 __EXCEPT_PAGE_FAULT
3247 SetLastError(STATUS_ACCESS_VIOLATION);
3248 ret = FALSE;
3250 __ENDTRY
3251 return ret;
3254 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
3255 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3256 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3258 BOOL ret;
3260 __TRY
3262 const CRYPT_BIT_BLOB *blob = pvStructInfo;
3263 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
3265 ret = TRUE;
3266 if (newBlob.cbData)
3268 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
3269 if (newBlob.pbData)
3271 DWORD i;
3273 for (i = 0; i < newBlob.cbData; i++)
3274 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
3276 else
3277 ret = FALSE;
3279 if (ret)
3280 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
3281 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3282 CryptMemFree(newBlob.pbData);
3284 __EXCEPT_PAGE_FAULT
3286 SetLastError(STATUS_ACCESS_VIOLATION);
3287 ret = FALSE;
3289 __ENDTRY
3290 return ret;
3293 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
3294 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3295 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3297 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
3299 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
3300 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3303 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
3304 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3305 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3307 BOOL ret;
3309 __TRY
3311 DWORD significantBytes, lenBytes, bytesNeeded;
3312 BYTE padByte = 0;
3313 BOOL pad = FALSE;
3314 const CRYPT_INTEGER_BLOB *blob = pvStructInfo;
3316 significantBytes = blob->cbData;
3317 if (significantBytes)
3319 if (blob->pbData[significantBytes - 1] & 0x80)
3321 /* negative, lop off leading (little-endian) 0xffs */
3322 for (; significantBytes > 0 &&
3323 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
3325 if (blob->pbData[significantBytes - 1] < 0x80)
3327 padByte = 0xff;
3328 pad = TRUE;
3331 else
3333 /* positive, lop off leading (little-endian) zeroes */
3334 for (; significantBytes > 0 &&
3335 !blob->pbData[significantBytes - 1]; significantBytes--)
3337 if (significantBytes == 0)
3338 significantBytes = 1;
3339 if (blob->pbData[significantBytes - 1] > 0x7f)
3341 padByte = 0;
3342 pad = TRUE;
3346 if (pad)
3347 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3348 else
3349 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3350 bytesNeeded = 1 + lenBytes + significantBytes;
3351 if (pad)
3352 bytesNeeded++;
3353 if (!pbEncoded)
3355 *pcbEncoded = bytesNeeded;
3356 ret = TRUE;
3358 else
3360 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3361 pcbEncoded, bytesNeeded)))
3363 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3364 pbEncoded = *(BYTE **)pbEncoded;
3365 *pbEncoded++ = ASN_INTEGER;
3366 if (pad)
3368 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3369 pbEncoded += lenBytes;
3370 *pbEncoded++ = padByte;
3372 else
3374 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3375 pbEncoded += lenBytes;
3377 for (; significantBytes > 0; significantBytes--)
3378 *(pbEncoded++) = blob->pbData[significantBytes - 1];
3382 __EXCEPT_PAGE_FAULT
3384 SetLastError(STATUS_ACCESS_VIOLATION);
3385 ret = FALSE;
3387 __ENDTRY
3388 return ret;
3391 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
3392 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3393 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3395 BOOL ret;
3397 __TRY
3399 DWORD significantBytes, lenBytes, bytesNeeded;
3400 BOOL pad = FALSE;
3401 const CRYPT_INTEGER_BLOB *blob = pvStructInfo;
3403 significantBytes = blob->cbData;
3404 if (significantBytes)
3406 /* positive, lop off leading (little-endian) zeroes */
3407 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
3408 significantBytes--)
3410 if (significantBytes == 0)
3411 significantBytes = 1;
3412 if (blob->pbData[significantBytes - 1] > 0x7f)
3413 pad = TRUE;
3415 if (pad)
3416 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3417 else
3418 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3419 bytesNeeded = 1 + lenBytes + significantBytes;
3420 if (pad)
3421 bytesNeeded++;
3422 if (!pbEncoded)
3424 *pcbEncoded = bytesNeeded;
3425 ret = TRUE;
3427 else
3429 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3430 pcbEncoded, bytesNeeded)))
3432 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3433 pbEncoded = *(BYTE **)pbEncoded;
3434 *pbEncoded++ = ASN_INTEGER;
3435 if (pad)
3437 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3438 pbEncoded += lenBytes;
3439 *pbEncoded++ = 0;
3441 else
3443 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3444 pbEncoded += lenBytes;
3446 for (; significantBytes > 0; significantBytes--)
3447 *(pbEncoded++) = blob->pbData[significantBytes - 1];
3451 __EXCEPT_PAGE_FAULT
3453 SetLastError(STATUS_ACCESS_VIOLATION);
3454 ret = FALSE;
3456 __ENDTRY
3457 return ret;
3460 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
3461 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3462 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3464 CRYPT_INTEGER_BLOB blob;
3465 BOOL ret;
3467 /* Encode as an unsigned integer, then change the tag to enumerated */
3468 blob.cbData = sizeof(DWORD);
3469 blob.pbData = (BYTE *)pvStructInfo;
3470 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
3471 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3472 if (ret && pbEncoded)
3474 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3475 pbEncoded = *(BYTE **)pbEncoded;
3476 pbEncoded[0] = ASN_ENUMERATED;
3478 return ret;
3481 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
3482 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3483 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3485 BOOL ret;
3487 __TRY
3489 SYSTEMTIME sysTime;
3490 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
3491 * temporary buffer because the output buffer is not NULL-terminated.
3493 char buf[16];
3494 static const DWORD bytesNeeded = sizeof(buf) - 1;
3496 if (!pbEncoded)
3498 *pcbEncoded = bytesNeeded;
3499 ret = TRUE;
3501 else
3503 /* Sanity check the year, this is a two-digit year format */
3504 ret = FileTimeToSystemTime(pvStructInfo, &sysTime);
3505 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
3507 SetLastError(CRYPT_E_BAD_ENCODE);
3508 ret = FALSE;
3510 if (ret)
3512 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3513 pbEncoded, pcbEncoded, bytesNeeded)))
3515 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3516 pbEncoded = *(BYTE **)pbEncoded;
3517 buf[0] = ASN_UTCTIME;
3518 buf[1] = bytesNeeded - 2;
3519 snprintf(buf + 2, sizeof(buf) - 2,
3520 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
3521 sysTime.wYear - 2000 : sysTime.wYear - 1900,
3522 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3523 sysTime.wMinute, sysTime.wSecond);
3524 memcpy(pbEncoded, buf, bytesNeeded);
3529 __EXCEPT_PAGE_FAULT
3531 SetLastError(STATUS_ACCESS_VIOLATION);
3532 ret = FALSE;
3534 __ENDTRY
3535 return ret;
3538 static BOOL CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
3539 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3540 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3542 BOOL ret;
3544 __TRY
3546 SYSTEMTIME sysTime;
3547 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
3548 * temporary buffer because the output buffer is not NULL-terminated.
3550 char buf[18];
3551 static const DWORD bytesNeeded = sizeof(buf) - 1;
3553 if (!pbEncoded)
3555 *pcbEncoded = bytesNeeded;
3556 ret = TRUE;
3558 else
3560 ret = FileTimeToSystemTime(pvStructInfo, &sysTime);
3561 if (ret)
3562 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3563 pcbEncoded, bytesNeeded);
3564 if (ret)
3566 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3567 pbEncoded = *(BYTE **)pbEncoded;
3568 buf[0] = ASN_GENERALTIME;
3569 buf[1] = bytesNeeded - 2;
3570 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
3571 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3572 sysTime.wMinute, sysTime.wSecond);
3573 memcpy(pbEncoded, buf, bytesNeeded);
3577 __EXCEPT_PAGE_FAULT
3579 SetLastError(STATUS_ACCESS_VIOLATION);
3580 ret = FALSE;
3582 __ENDTRY
3583 return ret;
3586 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
3587 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3588 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3590 BOOL ret;
3592 __TRY
3594 SYSTEMTIME sysTime;
3596 /* Check the year, if it's in the UTCTime range call that encode func */
3597 if (!FileTimeToSystemTime(pvStructInfo, &sysTime))
3598 return FALSE;
3599 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
3600 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
3601 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3602 else
3603 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
3604 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
3605 pcbEncoded);
3607 __EXCEPT_PAGE_FAULT
3609 SetLastError(STATUS_ACCESS_VIOLATION);
3610 ret = FALSE;
3612 __ENDTRY
3613 return ret;
3616 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
3617 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3618 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3620 BOOL ret;
3622 __TRY
3624 DWORD bytesNeeded, dataLen, lenBytes, i;
3625 const CRYPT_SEQUENCE_OF_ANY *seq = pvStructInfo;
3627 for (i = 0, dataLen = 0; i < seq->cValue; i++)
3628 dataLen += seq->rgValue[i].cbData;
3629 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3630 bytesNeeded = 1 + lenBytes + dataLen;
3631 if (!pbEncoded)
3633 *pcbEncoded = bytesNeeded;
3634 ret = TRUE;
3636 else
3638 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3639 pcbEncoded, bytesNeeded)))
3641 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3642 pbEncoded = *(BYTE **)pbEncoded;
3643 *pbEncoded++ = ASN_SEQUENCEOF;
3644 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
3645 pbEncoded += lenBytes;
3646 for (i = 0; i < seq->cValue; i++)
3648 memcpy(pbEncoded, seq->rgValue[i].pbData,
3649 seq->rgValue[i].cbData);
3650 pbEncoded += seq->rgValue[i].cbData;
3655 __EXCEPT_PAGE_FAULT
3657 SetLastError(STATUS_ACCESS_VIOLATION);
3658 ret = FALSE;
3660 __ENDTRY
3661 return ret;
3664 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
3665 BYTE *pbEncoded, DWORD *pcbEncoded)
3667 BOOL ret = TRUE;
3668 struct AsnEncodeSequenceItem items[3] = { { 0 } };
3669 struct AsnConstructedItem constructed = { 0 };
3670 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
3671 DWORD cItem = 0, cSwapped = 0;
3673 switch (distPoint->DistPointName.dwDistPointNameChoice)
3675 case CRL_DIST_POINT_NO_NAME:
3676 /* do nothing */
3677 break;
3678 case CRL_DIST_POINT_FULL_NAME:
3679 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3680 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
3681 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3682 constructed.tag = 0;
3683 constructed.pvStructInfo = &swapped[cSwapped];
3684 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3685 items[cItem].pvStructInfo = &constructed;
3686 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3687 cSwapped++;
3688 cItem++;
3689 break;
3690 case CRL_DIST_POINT_ISSUER_RDN_NAME:
3691 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3692 ret = FALSE;
3693 break;
3694 default:
3695 ret = FALSE;
3697 if (ret && distPoint->ReasonFlags.cbData)
3699 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3700 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
3701 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3702 items[cItem].pvStructInfo = &swapped[cSwapped];
3703 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3704 cSwapped++;
3705 cItem++;
3707 if (ret && distPoint->CRLIssuer.cAltEntry)
3709 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
3710 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
3711 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3712 items[cItem].pvStructInfo = &swapped[cSwapped];
3713 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3714 cSwapped++;
3715 cItem++;
3717 if (ret)
3718 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
3719 pbEncoded, pcbEncoded);
3720 return ret;
3723 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
3724 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3725 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3727 BOOL ret;
3729 __TRY
3731 const CRL_DIST_POINTS_INFO *info = pvStructInfo;
3733 if (!info->cDistPoint)
3735 SetLastError(E_INVALIDARG);
3736 ret = FALSE;
3738 else
3740 DWORD bytesNeeded, dataLen, lenBytes, i;
3742 ret = TRUE;
3743 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
3745 DWORD len;
3747 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
3748 &len);
3749 if (ret)
3750 dataLen += len;
3751 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
3753 /* Have to propagate index of failing character */
3754 *pcbEncoded = len;
3757 if (ret)
3759 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3760 bytesNeeded = 1 + lenBytes + dataLen;
3761 if (!pbEncoded)
3763 *pcbEncoded = bytesNeeded;
3764 ret = TRUE;
3766 else
3768 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3769 pbEncoded, pcbEncoded, bytesNeeded)))
3771 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3772 pbEncoded = *(BYTE **)pbEncoded;
3773 *pbEncoded++ = ASN_SEQUENCEOF;
3774 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
3775 pbEncoded += lenBytes;
3776 for (i = 0; ret && i < info->cDistPoint; i++)
3778 DWORD len = dataLen;
3780 ret = CRYPT_AsnEncodeDistPoint(
3781 &info->rgDistPoint[i], pbEncoded, &len);
3782 if (ret)
3784 pbEncoded += len;
3785 dataLen -= len;
3793 __EXCEPT_PAGE_FAULT
3795 SetLastError(STATUS_ACCESS_VIOLATION);
3796 ret = FALSE;
3798 __ENDTRY
3799 return ret;
3802 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3803 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3804 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3806 BOOL ret;
3808 __TRY
3810 const CERT_ENHKEY_USAGE *usage = pvStructInfo;
3811 DWORD bytesNeeded = 0, lenBytes, size, i;
3813 ret = TRUE;
3814 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3816 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3817 usage->rgpszUsageIdentifier[i],
3818 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
3819 if (ret)
3820 bytesNeeded += size;
3822 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3823 bytesNeeded += 1 + lenBytes;
3824 if (ret)
3826 if (!pbEncoded)
3827 *pcbEncoded = bytesNeeded;
3828 else
3830 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3831 pbEncoded, pcbEncoded, bytesNeeded)))
3833 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3834 pbEncoded = *(BYTE **)pbEncoded;
3835 *pbEncoded++ = ASN_SEQUENCEOF;
3836 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
3837 &lenBytes);
3838 pbEncoded += lenBytes;
3839 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3841 size = bytesNeeded;
3842 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3843 usage->rgpszUsageIdentifier[i],
3844 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
3845 &size);
3846 if (ret)
3848 pbEncoded += size;
3849 bytesNeeded -= size;
3856 __EXCEPT_PAGE_FAULT
3858 SetLastError(STATUS_ACCESS_VIOLATION);
3859 ret = FALSE;
3861 __ENDTRY
3862 return ret;
3865 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
3866 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3867 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3869 BOOL ret;
3871 __TRY
3873 const CRL_ISSUING_DIST_POINT *point = pvStructInfo;
3874 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3875 struct AsnConstructedItem constructed = { 0 };
3876 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3877 DWORD cItem = 0, cSwapped = 0;
3879 ret = TRUE;
3880 switch (point->DistPointName.dwDistPointNameChoice)
3882 case CRL_DIST_POINT_NO_NAME:
3883 /* do nothing */
3884 break;
3885 case CRL_DIST_POINT_FULL_NAME:
3886 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3887 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3888 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3889 constructed.tag = 0;
3890 constructed.pvStructInfo = &swapped[cSwapped];
3891 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3892 items[cItem].pvStructInfo = &constructed;
3893 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3894 cSwapped++;
3895 cItem++;
3896 break;
3897 default:
3898 SetLastError(E_INVALIDARG);
3899 ret = FALSE;
3901 if (ret && point->fOnlyContainsUserCerts)
3903 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3904 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3905 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3906 items[cItem].pvStructInfo = &swapped[cSwapped];
3907 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3908 cSwapped++;
3909 cItem++;
3911 if (ret && point->fOnlyContainsCACerts)
3913 swapped[cSwapped].tag = ASN_CONTEXT | 2;
3914 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3915 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3916 items[cItem].pvStructInfo = &swapped[cSwapped];
3917 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3918 cSwapped++;
3919 cItem++;
3921 if (ret && point->OnlySomeReasonFlags.cbData)
3923 swapped[cSwapped].tag = ASN_CONTEXT | 3;
3924 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3925 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3926 items[cItem].pvStructInfo = &swapped[cSwapped];
3927 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3928 cSwapped++;
3929 cItem++;
3931 if (ret && point->fIndirectCRL)
3933 swapped[cSwapped].tag = ASN_CONTEXT | 4;
3934 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
3935 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3936 items[cItem].pvStructInfo = &swapped[cSwapped];
3937 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3938 cSwapped++;
3939 cItem++;
3941 if (ret)
3942 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3943 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3945 __EXCEPT_PAGE_FAULT
3947 SetLastError(STATUS_ACCESS_VIOLATION);
3948 ret = FALSE;
3950 __ENDTRY
3951 return ret;
3954 static BOOL CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType,
3955 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3956 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3958 BOOL ret;
3959 const CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
3960 struct AsnEncodeSequenceItem items[3] = {
3961 { &subtree->Base, CRYPT_AsnEncodeAltNameEntry, 0 },
3962 { 0 }
3964 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3965 DWORD cItem = 1, cSwapped = 0;
3967 if (subtree->dwMinimum)
3969 swapped[cSwapped].tag = ASN_CONTEXT | 0;
3970 swapped[cSwapped].pvStructInfo = &subtree->dwMinimum;
3971 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3972 items[cItem].pvStructInfo = &swapped[cSwapped];
3973 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3974 cSwapped++;
3975 cItem++;
3977 if (subtree->fMaximum)
3979 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3980 swapped[cSwapped].pvStructInfo = &subtree->dwMaximum;
3981 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3982 items[cItem].pvStructInfo = &swapped[cSwapped];
3983 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3984 cSwapped++;
3985 cItem++;
3987 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags,
3988 pEncodePara, pbEncoded, pcbEncoded);
3989 return ret;
3992 static BOOL WINAPI CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType,
3993 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3994 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3996 BOOL ret = FALSE;
3997 CRYPT_BLOB_ARRAY permitted = { 0, NULL }, excluded = { 0, NULL };
3999 TRACE("%p\n", pvStructInfo);
4001 __TRY
4003 const CERT_NAME_CONSTRAINTS_INFO *constraints = pvStructInfo;
4004 struct AsnEncodeSequenceItem items[2] = { { 0 } };
4005 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4006 DWORD i, cItem = 0, cSwapped = 0;
4008 ret = TRUE;
4009 if (constraints->cPermittedSubtree)
4011 permitted.rgBlob = CryptMemAlloc(
4012 constraints->cPermittedSubtree * sizeof(CRYPT_DER_BLOB));
4013 if (permitted.rgBlob)
4015 permitted.cBlob = constraints->cPermittedSubtree;
4016 memset(permitted.rgBlob, 0,
4017 permitted.cBlob * sizeof(CRYPT_DER_BLOB));
4018 for (i = 0; ret && i < permitted.cBlob; i++)
4019 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
4020 NULL, &constraints->rgPermittedSubtree[i],
4021 CRYPT_ENCODE_ALLOC_FLAG, NULL,
4022 (BYTE *)&permitted.rgBlob[i].pbData,
4023 &permitted.rgBlob[i].cbData);
4024 if (ret)
4026 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4027 swapped[cSwapped].pvStructInfo = &permitted;
4028 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
4029 items[cItem].pvStructInfo = &swapped[cSwapped];
4030 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4031 cSwapped++;
4032 cItem++;
4035 else
4036 ret = FALSE;
4038 if (constraints->cExcludedSubtree)
4040 excluded.rgBlob = CryptMemAlloc(
4041 constraints->cExcludedSubtree * sizeof(CRYPT_DER_BLOB));
4042 if (excluded.rgBlob)
4044 excluded.cBlob = constraints->cExcludedSubtree;
4045 memset(excluded.rgBlob, 0,
4046 excluded.cBlob * sizeof(CRYPT_DER_BLOB));
4047 for (i = 0; ret && i < excluded.cBlob; i++)
4048 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
4049 NULL, &constraints->rgExcludedSubtree[i],
4050 CRYPT_ENCODE_ALLOC_FLAG, NULL,
4051 (BYTE *)&excluded.rgBlob[i].pbData,
4052 &excluded.rgBlob[i].cbData);
4053 if (ret)
4055 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4056 swapped[cSwapped].pvStructInfo = &excluded;
4057 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
4058 items[cItem].pvStructInfo = &swapped[cSwapped];
4059 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4060 cSwapped++;
4061 cItem++;
4064 else
4065 ret = FALSE;
4067 if (ret)
4068 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4069 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4070 for (i = 0; i < permitted.cBlob; i++)
4071 LocalFree(permitted.rgBlob[i].pbData);
4072 for (i = 0; i < excluded.cBlob; i++)
4073 LocalFree(excluded.rgBlob[i].pbData);
4075 __EXCEPT_PAGE_FAULT
4077 SetLastError(STATUS_ACCESS_VIOLATION);
4079 __ENDTRY
4080 CryptMemFree(permitted.rgBlob);
4081 CryptMemFree(excluded.rgBlob);
4082 TRACE("returning %d\n", ret);
4083 return ret;
4086 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
4087 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
4088 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
4089 DWORD *pcbEncoded)
4091 BOOL ret;
4092 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
4093 struct AsnEncodeSequenceItem items[] = {
4094 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
4095 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
4098 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4099 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
4100 pcbEncoded);
4101 return ret;
4104 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
4105 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4106 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4108 BOOL ret = FALSE;
4110 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
4112 SetLastError(E_INVALIDARG);
4113 return FALSE;
4116 __TRY
4118 const CMSG_SIGNER_INFO *info = pvStructInfo;
4120 if (!info->Issuer.cbData)
4121 SetLastError(E_INVALIDARG);
4122 else
4124 struct AsnEncodeSequenceItem items[7] = {
4125 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4126 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
4127 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
4128 0 },
4130 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4131 DWORD cItem = 3, cSwapped = 0;
4133 if (info->AuthAttrs.cAttr)
4135 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4136 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
4137 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4138 items[cItem].pvStructInfo = &swapped[cSwapped];
4139 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4140 cSwapped++;
4141 cItem++;
4143 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
4144 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4145 cItem++;
4146 items[cItem].pvStructInfo = &info->EncryptedHash;
4147 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
4148 cItem++;
4149 if (info->UnauthAttrs.cAttr)
4151 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4152 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
4153 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4154 items[cItem].pvStructInfo = &swapped[cSwapped];
4155 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4156 cSwapped++;
4157 cItem++;
4159 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4160 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4163 __EXCEPT_PAGE_FAULT
4165 SetLastError(STATUS_ACCESS_VIOLATION);
4167 __ENDTRY
4168 return ret;
4171 static BOOL WINAPI CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType,
4172 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4173 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4175 BOOL ret = FALSE;
4177 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
4179 SetLastError(E_INVALIDARG);
4180 return FALSE;
4183 __TRY
4185 const CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
4187 if (info->SignerId.dwIdChoice != CERT_ID_ISSUER_SERIAL_NUMBER &&
4188 info->SignerId.dwIdChoice != CERT_ID_KEY_IDENTIFIER)
4189 SetLastError(E_INVALIDARG);
4190 else if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER &&
4191 !info->SignerId.u.IssuerSerialNumber.Issuer.cbData)
4192 SetLastError(E_INVALIDARG);
4193 else
4195 struct AsnEncodeSequenceItem items[7] = {
4196 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4198 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
4199 DWORD cItem = 1, cSwapped = 0;
4201 if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
4203 items[cItem].pvStructInfo =
4204 &info->SignerId.u.IssuerSerialNumber.Issuer;
4205 items[cItem].encodeFunc =
4206 CRYPT_AsnEncodeIssuerSerialNumber;
4207 cItem++;
4209 else
4211 swapped[cSwapped].tag = ASN_CONTEXT | 0;
4212 swapped[cSwapped].pvStructInfo = &info->SignerId.u.KeyId;
4213 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
4214 items[cItem].pvStructInfo = &swapped[cSwapped];
4215 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4216 cSwapped++;
4217 cItem++;
4219 items[cItem].pvStructInfo = &info->HashAlgorithm;
4220 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4221 cItem++;
4222 if (info->AuthAttrs.cAttr)
4224 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4225 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
4226 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4227 items[cItem].pvStructInfo = &swapped[cSwapped];
4228 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4229 cSwapped++;
4230 cItem++;
4232 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
4233 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4234 cItem++;
4235 items[cItem].pvStructInfo = &info->EncryptedHash;
4236 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
4237 cItem++;
4238 if (info->UnauthAttrs.cAttr)
4240 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4241 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
4242 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4243 items[cItem].pvStructInfo = &swapped[cSwapped];
4244 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4245 cSwapped++;
4246 cItem++;
4248 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4249 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4252 __EXCEPT_PAGE_FAULT
4254 SetLastError(STATUS_ACCESS_VIOLATION);
4256 __ENDTRY
4257 return ret;
4260 BOOL CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
4261 DWORD *pcbData)
4263 struct AsnEncodeSequenceItem items[7] = {
4264 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
4266 struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 };
4267 struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 };
4268 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4269 DWORD cItem = 1, cSwapped = 0;
4270 BOOL ret = TRUE;
4272 if (signedInfo->cSignerInfo)
4274 digestAlgorithmsSet.cItems = signedInfo->cSignerInfo;
4275 digestAlgorithmsSet.items = signedInfo->rgSignerInfo;
4276 digestAlgorithmsSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
4277 digestAlgorithmsSet.itemOffset =
4278 offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm);
4279 digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4280 items[cItem].pvStructInfo = &digestAlgorithmsSet;
4281 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4282 cItem++;
4284 items[cItem].pvStructInfo = &signedInfo->content;
4285 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal;
4286 cItem++;
4287 if (signedInfo->cCertEncoded)
4289 certSet.cItems = signedInfo->cCertEncoded;
4290 certSet.items = signedInfo->rgCertEncoded;
4291 certSet.itemSize = sizeof(CERT_BLOB);
4292 certSet.itemOffset = 0;
4293 certSet.encode = CRYPT_CopyEncodedBlob;
4294 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0;
4295 swapped[cSwapped].pvStructInfo = &certSet;
4296 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4297 items[cItem].pvStructInfo = &swapped[cSwapped];
4298 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4299 cSwapped++;
4300 cItem++;
4302 if (signedInfo->cCrlEncoded)
4304 crlSet.cItems = signedInfo->cCrlEncoded;
4305 crlSet.items = signedInfo->rgCrlEncoded;
4306 crlSet.itemSize = sizeof(CRL_BLOB);
4307 crlSet.itemOffset = 0;
4308 crlSet.encode = CRYPT_CopyEncodedBlob;
4309 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
4310 swapped[cSwapped].pvStructInfo = &crlSet;
4311 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4312 items[cItem].pvStructInfo = &swapped[cSwapped];
4313 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4314 cSwapped++;
4315 cItem++;
4317 if (ret && signedInfo->cSignerInfo)
4319 signerSet.cItems = signedInfo->cSignerInfo;
4320 signerSet.items = signedInfo->rgSignerInfo;
4321 signerSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
4322 signerSet.itemOffset = 0;
4323 signerSet.encode = CRYPT_AsnEncodeCMSSignerInfo;
4324 items[cItem].pvStructInfo = &signerSet;
4325 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4326 cItem++;
4328 if (ret)
4329 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
4330 items, cItem, 0, NULL, pvData, pcbData);
4332 return ret;
4335 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
4336 LPCSTR lpszStructType)
4338 CryptEncodeObjectExFunc encodeFunc = NULL;
4340 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4341 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4343 SetLastError(ERROR_FILE_NOT_FOUND);
4344 return NULL;
4347 if (!HIWORD(lpszStructType))
4349 switch (LOWORD(lpszStructType))
4351 case LOWORD(X509_CERT):
4352 encodeFunc = CRYPT_AsnEncodeCert;
4353 break;
4354 case LOWORD(X509_CERT_TO_BE_SIGNED):
4355 encodeFunc = CRYPT_AsnEncodeCertInfo;
4356 break;
4357 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
4358 encodeFunc = CRYPT_AsnEncodeCRLInfo;
4359 break;
4360 case LOWORD(X509_EXTENSIONS):
4361 encodeFunc = CRYPT_AsnEncodeExtensions;
4362 break;
4363 case LOWORD(X509_NAME_VALUE):
4364 encodeFunc = CRYPT_AsnEncodeNameValue;
4365 break;
4366 case LOWORD(X509_NAME):
4367 encodeFunc = CRYPT_AsnEncodeName;
4368 break;
4369 case LOWORD(X509_PUBLIC_KEY_INFO):
4370 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
4371 break;
4372 case LOWORD(X509_AUTHORITY_KEY_ID):
4373 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
4374 break;
4375 case LOWORD(X509_ALTERNATE_NAME):
4376 encodeFunc = CRYPT_AsnEncodeAltName;
4377 break;
4378 case LOWORD(X509_BASIC_CONSTRAINTS):
4379 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
4380 break;
4381 case LOWORD(X509_BASIC_CONSTRAINTS2):
4382 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
4383 break;
4384 case LOWORD(X509_CERT_POLICIES):
4385 encodeFunc = CRYPT_AsnEncodeCertPolicies;
4386 break;
4387 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
4388 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
4389 break;
4390 case LOWORD(X509_UNICODE_NAME):
4391 encodeFunc = CRYPT_AsnEncodeUnicodeName;
4392 break;
4393 case LOWORD(PKCS_CONTENT_INFO):
4394 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
4395 break;
4396 case LOWORD(PKCS_ATTRIBUTE):
4397 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
4398 break;
4399 case LOWORD(X509_UNICODE_NAME_VALUE):
4400 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
4401 break;
4402 case LOWORD(X509_OCTET_STRING):
4403 encodeFunc = CRYPT_AsnEncodeOctets;
4404 break;
4405 case LOWORD(X509_BITS):
4406 case LOWORD(X509_KEY_USAGE):
4407 encodeFunc = CRYPT_AsnEncodeBits;
4408 break;
4409 case LOWORD(X509_INTEGER):
4410 encodeFunc = CRYPT_AsnEncodeInt;
4411 break;
4412 case LOWORD(X509_MULTI_BYTE_INTEGER):
4413 encodeFunc = CRYPT_AsnEncodeInteger;
4414 break;
4415 case LOWORD(X509_MULTI_BYTE_UINT):
4416 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
4417 break;
4418 case LOWORD(X509_ENUMERATED):
4419 encodeFunc = CRYPT_AsnEncodeEnumerated;
4420 break;
4421 case LOWORD(X509_CHOICE_OF_TIME):
4422 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
4423 break;
4424 case LOWORD(X509_AUTHORITY_KEY_ID2):
4425 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
4426 break;
4427 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
4428 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
4429 break;
4430 case LOWORD(X509_SEQUENCE_OF_ANY):
4431 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
4432 break;
4433 case LOWORD(PKCS_UTC_TIME):
4434 encodeFunc = CRYPT_AsnEncodeUtcTime;
4435 break;
4436 case LOWORD(X509_CRL_DIST_POINTS):
4437 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
4438 break;
4439 case LOWORD(X509_ENHANCED_KEY_USAGE):
4440 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
4441 break;
4442 case LOWORD(PKCS_CTL):
4443 encodeFunc = CRYPT_AsnEncodeCTL;
4444 break;
4445 case LOWORD(PKCS_SMIME_CAPABILITIES):
4446 encodeFunc = CRYPT_AsnEncodeSMIMECapabilities;
4447 break;
4448 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
4449 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
4450 break;
4451 case LOWORD(PKCS_ATTRIBUTES):
4452 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4453 break;
4454 case LOWORD(X509_ISSUING_DIST_POINT):
4455 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
4456 break;
4457 case LOWORD(X509_NAME_CONSTRAINTS):
4458 encodeFunc = CRYPT_AsnEncodeNameConstraints;
4459 break;
4460 case LOWORD(X509_POLICY_MAPPINGS):
4461 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
4462 break;
4463 case LOWORD(X509_POLICY_CONSTRAINTS):
4464 encodeFunc = CRYPT_AsnEncodeCertPolicyConstraints;
4465 break;
4466 case LOWORD(PKCS7_SIGNER_INFO):
4467 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
4468 break;
4469 case LOWORD(CMS_SIGNER_INFO):
4470 encodeFunc = CRYPT_AsnEncodeCMSSignerInfo;
4471 break;
4474 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4475 encodeFunc = CRYPT_AsnEncodeExtensions;
4476 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4477 encodeFunc = CRYPT_AsnEncodeUtcTime;
4478 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
4479 encodeFunc = CRYPT_AsnEncodeUtcTime;
4480 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4481 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
4482 else if (!strcmp(lpszStructType, szOID_LEGACY_POLICY_MAPPINGS))
4483 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
4484 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4485 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
4486 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4487 encodeFunc = CRYPT_AsnEncodeEnumerated;
4488 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4489 encodeFunc = CRYPT_AsnEncodeBits;
4490 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4491 encodeFunc = CRYPT_AsnEncodeOctets;
4492 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4493 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
4494 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4495 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
4496 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4497 encodeFunc = CRYPT_AsnEncodeAltName;
4498 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4499 encodeFunc = CRYPT_AsnEncodeAltName;
4500 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4501 encodeFunc = CRYPT_AsnEncodeAltName;
4502 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4503 encodeFunc = CRYPT_AsnEncodeAltName;
4504 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4505 encodeFunc = CRYPT_AsnEncodeAltName;
4506 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4507 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
4508 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
4509 encodeFunc = CRYPT_AsnEncodeCertPolicies;
4510 else if (!strcmp(lpszStructType, szOID_POLICY_MAPPINGS))
4511 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
4512 else if (!strcmp(lpszStructType, szOID_POLICY_CONSTRAINTS))
4513 encodeFunc = CRYPT_AsnEncodeCertPolicyConstraints;
4514 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4515 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
4516 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4517 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
4518 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
4519 encodeFunc = CRYPT_AsnEncodeNameConstraints;
4520 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
4521 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
4522 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
4523 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
4524 else if (!strcmp(lpszStructType, szOID_CTL))
4525 encodeFunc = CRYPT_AsnEncodeCTL;
4526 return encodeFunc;
4529 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType,
4530 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4532 static HCRYPTOIDFUNCSET set = NULL;
4533 CryptEncodeObjectFunc encodeFunc = NULL;
4535 if (!set)
4536 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
4537 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4538 (void **)&encodeFunc, hFunc);
4539 return encodeFunc;
4542 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType,
4543 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4545 static HCRYPTOIDFUNCSET set = NULL;
4546 CryptEncodeObjectExFunc encodeFunc = NULL;
4548 if (!set)
4549 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
4550 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4551 (void **)&encodeFunc, hFunc);
4552 return encodeFunc;
4555 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4556 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
4558 BOOL ret = FALSE;
4559 HCRYPTOIDFUNCADDR hFunc = NULL;
4560 CryptEncodeObjectFunc pCryptEncodeObject = NULL;
4561 CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL;
4563 TRACE_(crypt)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
4564 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
4565 pcbEncoded);
4567 if (!pbEncoded && !pcbEncoded)
4569 SetLastError(ERROR_INVALID_PARAMETER);
4570 return FALSE;
4573 if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType,
4574 lpszStructType)))
4576 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4577 debugstr_a(lpszStructType));
4578 pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType,
4579 lpszStructType, &hFunc);
4580 if (!pCryptEncodeObject)
4581 pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType,
4582 lpszStructType, &hFunc);
4584 if (pCryptEncodeObject)
4585 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4586 pvStructInfo, pbEncoded, pcbEncoded);
4587 else if (pCryptEncodeObjectEx)
4588 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
4589 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
4590 if (hFunc)
4591 CryptFreeOIDFunctionAddress(hFunc, 0);
4592 TRACE_(crypt)("returning %d\n", ret);
4593 return ret;
4596 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4597 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
4598 void *pvEncoded, DWORD *pcbEncoded)
4600 BOOL ret = FALSE;
4601 HCRYPTOIDFUNCADDR hFunc = NULL;
4602 CryptEncodeObjectExFunc encodeFunc = NULL;
4604 TRACE_(crypt)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
4605 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
4606 pvEncoded, pcbEncoded);
4608 if (!pvEncoded && !pcbEncoded)
4610 SetLastError(ERROR_INVALID_PARAMETER);
4611 return FALSE;
4614 SetLastError(NOERROR);
4615 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
4616 *(BYTE **)pvEncoded = NULL;
4617 encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType);
4618 if (!encodeFunc)
4620 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4621 debugstr_a(lpszStructType));
4622 encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType,
4623 &hFunc);
4625 if (encodeFunc)
4626 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
4627 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
4628 else
4630 CryptEncodeObjectFunc pCryptEncodeObject =
4631 CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4633 if (pCryptEncodeObject)
4635 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
4637 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4638 pvStructInfo, NULL, pcbEncoded);
4639 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
4640 pvEncoded, pcbEncoded, *pcbEncoded)))
4641 ret = pCryptEncodeObject(dwCertEncodingType,
4642 lpszStructType, pvStructInfo, *(BYTE **)pvEncoded,
4643 pcbEncoded);
4645 else
4646 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4647 pvStructInfo, pvEncoded, pcbEncoded);
4650 if (hFunc)
4651 CryptFreeOIDFunctionAddress(hFunc, 0);
4652 TRACE_(crypt)("returning %d\n", ret);
4653 return ret;
4656 BOOL WINAPI PFXExportCertStore(HCERTSTORE hStore, CRYPT_DATA_BLOB *pPFX,
4657 LPCWSTR szPassword, DWORD dwFlags)
4659 return PFXExportCertStoreEx(hStore, pPFX, szPassword, NULL, dwFlags);
4662 BOOL WINAPI PFXExportCertStoreEx(HCERTSTORE hStore, CRYPT_DATA_BLOB *pPFX,
4663 LPCWSTR szPassword, void *pvReserved, DWORD dwFlags)
4665 FIXME_(crypt)("(%p, %p, %p, %p, %08x): stub\n", hStore, pPFX, szPassword,
4666 pvReserved, dwFlags);
4667 return FALSE;
4670 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
4671 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4673 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
4674 NULL, 0, NULL, pInfo, pcbInfo);
4677 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
4678 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
4679 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4681 BOOL ret;
4682 HCRYPTKEY key;
4683 static CHAR oid[] = szOID_RSA_RSA;
4685 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
4686 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
4687 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
4689 if (!pszPublicKeyObjId)
4690 pszPublicKeyObjId = oid;
4691 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
4693 DWORD keySize = 0;
4695 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
4696 if (ret)
4698 LPBYTE pubKey = CryptMemAlloc(keySize);
4700 if (pubKey)
4702 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
4703 &keySize);
4704 if (ret)
4706 DWORD encodedLen = 0;
4708 ret = CryptEncodeObject(dwCertEncodingType,
4709 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
4710 if (ret)
4712 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
4713 strlen(pszPublicKeyObjId) + 1 + encodedLen;
4715 if (!pInfo)
4716 *pcbInfo = sizeNeeded;
4717 else if (*pcbInfo < sizeNeeded)
4719 SetLastError(ERROR_MORE_DATA);
4720 *pcbInfo = sizeNeeded;
4721 ret = FALSE;
4723 else
4725 *pcbInfo = sizeNeeded;
4726 pInfo->Algorithm.pszObjId = (char *)pInfo +
4727 sizeof(CERT_PUBLIC_KEY_INFO);
4728 lstrcpyA(pInfo->Algorithm.pszObjId,
4729 pszPublicKeyObjId);
4730 pInfo->Algorithm.Parameters.cbData = 0;
4731 pInfo->Algorithm.Parameters.pbData = NULL;
4732 pInfo->PublicKey.pbData =
4733 (BYTE *)pInfo->Algorithm.pszObjId
4734 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
4735 pInfo->PublicKey.cbData = encodedLen;
4736 pInfo->PublicKey.cUnusedBits = 0;
4737 ret = CryptEncodeObject(dwCertEncodingType,
4738 RSA_CSP_PUBLICKEYBLOB, pubKey,
4739 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
4743 CryptMemFree(pubKey);
4745 else
4746 ret = FALSE;
4748 CryptDestroyKey(key);
4750 return ret;
4753 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
4754 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
4755 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
4757 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
4758 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
4759 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4761 static HCRYPTOIDFUNCSET set = NULL;
4762 BOOL ret;
4763 ExportPublicKeyInfoExFunc exportFunc = NULL;
4764 HCRYPTOIDFUNCADDR hFunc = NULL;
4766 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
4767 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
4768 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
4770 if (!hCryptProv)
4772 SetLastError(ERROR_INVALID_PARAMETER);
4773 return FALSE;
4776 if (pszPublicKeyObjId)
4778 if (!set)
4779 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
4781 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
4782 0, (void **)&exportFunc, &hFunc);
4784 if (!exportFunc)
4785 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
4786 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
4787 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
4788 if (hFunc)
4789 CryptFreeOIDFunctionAddress(hFunc, 0);
4790 return ret;
4793 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
4794 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
4796 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
4797 0, 0, NULL, phKey);
4800 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
4801 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4802 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
4804 BOOL ret;
4805 DWORD pubKeySize = 0;
4807 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
4808 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
4810 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
4811 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
4812 if (ret)
4814 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
4816 if (pubKey)
4818 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
4819 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
4820 &pubKeySize);
4821 if (ret)
4823 if(aiKeyAlg)
4824 ((BLOBHEADER*)pubKey)->aiKeyAlg = aiKeyAlg;
4825 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
4826 phKey);
4828 CryptMemFree(pubKey);
4830 else
4831 ret = FALSE;
4833 return ret;
4836 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
4837 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4838 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
4840 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
4841 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4842 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
4844 static HCRYPTOIDFUNCSET set = NULL;
4845 BOOL ret;
4846 ImportPublicKeyInfoExFunc importFunc = NULL;
4847 HCRYPTOIDFUNCADDR hFunc = NULL;
4849 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
4850 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
4852 if (!set)
4853 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
4854 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
4855 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
4856 if (!importFunc)
4857 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
4858 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
4859 pvAuxInfo, phKey);
4860 if (hFunc)
4861 CryptFreeOIDFunctionAddress(hFunc, 0);
4862 return ret;