push 378fe7a60681a28e8b22f62dcfe122d585b92570
[wine/hacks.git] / dlls / crypt32 / encode.c
blob14d193fb3a6b7dccd034fe3e771810398848c8bf
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_AsnEncodeAlgorithmId, 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 /* Like in Windows, this blithely ignores the validity of the passed-in
468 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
469 * decode properly, see CRYPT_AsnDecodeCertInfo.
471 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
472 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
473 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
475 BOOL ret;
477 __TRY
479 const CERT_INFO *info = pvStructInfo;
480 struct AsnEncodeSequenceItem items[10] = {
481 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
482 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
483 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
484 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
485 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
486 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
487 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfo, 0 },
488 { 0 }
490 struct AsnConstructedItem constructed[3] = { { 0 } };
491 DWORD cItem = 7, cConstructed = 0;
493 if (info->IssuerUniqueId.cbData)
495 constructed[cConstructed].tag = 1;
496 constructed[cConstructed].pvStructInfo = &info->IssuerUniqueId;
497 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
498 items[cItem].pvStructInfo = &constructed[cConstructed];
499 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
500 cConstructed++;
501 cItem++;
503 if (info->SubjectUniqueId.cbData)
505 constructed[cConstructed].tag = 2;
506 constructed[cConstructed].pvStructInfo = &info->SubjectUniqueId;
507 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
508 items[cItem].pvStructInfo = &constructed[cConstructed];
509 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
510 cConstructed++;
511 cItem++;
513 if (info->cExtension)
515 constructed[cConstructed].tag = 3;
516 constructed[cConstructed].pvStructInfo = &info->cExtension;
517 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
518 items[cItem].pvStructInfo = &constructed[cConstructed];
519 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
520 cConstructed++;
521 cItem++;
524 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
525 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
527 __EXCEPT_PAGE_FAULT
529 SetLastError(STATUS_ACCESS_VIOLATION);
530 ret = FALSE;
532 __ENDTRY
533 return ret;
536 static BOOL CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
537 BYTE *pbEncoded, DWORD *pcbEncoded)
539 struct AsnEncodeSequenceItem items[3] = {
540 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
541 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
542 { 0 }
544 DWORD cItem = 2;
545 BOOL ret;
547 TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded);
549 if (entry->cExtension)
551 items[cItem].pvStructInfo = &entry->cExtension;
552 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
553 cItem++;
556 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
557 pbEncoded, pcbEncoded);
559 TRACE("returning %d (%08x)\n", ret, GetLastError());
560 return ret;
563 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
564 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
565 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
567 DWORD cCRLEntry = *(const DWORD *)pvStructInfo;
568 DWORD bytesNeeded, dataLen, lenBytes, i;
569 const CRL_ENTRY *rgCRLEntry = *(const CRL_ENTRY *const *)
570 ((const BYTE *)pvStructInfo + sizeof(DWORD));
571 BOOL ret = TRUE;
573 for (i = 0, dataLen = 0; ret && i < cCRLEntry; i++)
575 DWORD size;
577 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
578 if (ret)
579 dataLen += size;
581 if (ret)
583 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
584 bytesNeeded = 1 + lenBytes + dataLen;
585 if (!pbEncoded)
586 *pcbEncoded = bytesNeeded;
587 else
589 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
590 pcbEncoded, bytesNeeded)))
592 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
593 pbEncoded = *(BYTE **)pbEncoded;
594 *pbEncoded++ = ASN_SEQUENCEOF;
595 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
596 pbEncoded += lenBytes;
597 for (i = 0; i < cCRLEntry; i++)
599 DWORD size = dataLen;
601 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], pbEncoded,
602 &size);
603 pbEncoded += size;
604 dataLen -= size;
609 return ret;
612 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
613 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
614 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
616 const DWORD *ver = pvStructInfo;
617 BOOL ret;
619 /* CRL_V1 is not encoded */
620 if (*ver == CRL_V1)
622 *pcbEncoded = 0;
623 ret = TRUE;
625 else
626 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
627 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
628 return ret;
631 /* Like in Windows, this blithely ignores the validity of the passed-in
632 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
633 * decode properly, see CRYPT_AsnDecodeCRLInfo.
635 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
636 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
637 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
639 BOOL ret;
641 __TRY
643 const CRL_INFO *info = pvStructInfo;
644 struct AsnEncodeSequenceItem items[7] = {
645 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
646 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
647 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
648 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
649 { 0 }
651 struct AsnConstructedItem constructed[1] = { { 0 } };
652 DWORD cItem = 4, cConstructed = 0;
654 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
656 items[cItem].pvStructInfo = &info->NextUpdate;
657 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
658 cItem++;
660 if (info->cCRLEntry)
662 items[cItem].pvStructInfo = &info->cCRLEntry;
663 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
664 cItem++;
666 if (info->cExtension)
668 constructed[cConstructed].tag = 0;
669 constructed[cConstructed].pvStructInfo = &info->cExtension;
670 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
671 items[cItem].pvStructInfo = &constructed[cConstructed];
672 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
673 cConstructed++;
674 cItem++;
677 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
678 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
680 __EXCEPT_PAGE_FAULT
682 SetLastError(STATUS_ACCESS_VIOLATION);
683 ret = FALSE;
685 __ENDTRY
686 return ret;
689 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
690 DWORD *pcbEncoded)
692 BOOL ret;
693 struct AsnEncodeSequenceItem items[3] = {
694 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
695 { NULL, NULL, 0 },
696 { NULL, NULL, 0 },
698 DWORD cItem = 1;
700 TRACE("%p, %p, %d\n", ext, pbEncoded, *pcbEncoded);
702 if (ext->fCritical)
704 items[cItem].pvStructInfo = &ext->fCritical;
705 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
706 cItem++;
708 items[cItem].pvStructInfo = &ext->Value;
709 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
710 cItem++;
712 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
713 pbEncoded, pcbEncoded);
714 TRACE("returning %d (%08x)\n", ret, GetLastError());
715 return ret;
718 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
719 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
720 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
722 BOOL ret;
724 __TRY
726 DWORD bytesNeeded, dataLen, lenBytes, i;
727 const CERT_EXTENSIONS *exts = pvStructInfo;
729 ret = TRUE;
730 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
732 DWORD size;
734 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
735 if (ret)
736 dataLen += size;
738 if (ret)
740 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
741 bytesNeeded = 1 + lenBytes + dataLen;
742 if (!pbEncoded)
743 *pcbEncoded = bytesNeeded;
744 else
746 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
747 pbEncoded, pcbEncoded, bytesNeeded)))
749 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
750 pbEncoded = *(BYTE **)pbEncoded;
751 *pbEncoded++ = ASN_SEQUENCEOF;
752 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
753 pbEncoded += lenBytes;
754 for (i = 0; i < exts->cExtension; i++)
756 DWORD size = dataLen;
758 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
759 pbEncoded, &size);
760 pbEncoded += size;
761 dataLen -= size;
767 __EXCEPT_PAGE_FAULT
769 SetLastError(STATUS_ACCESS_VIOLATION);
770 ret = FALSE;
772 __ENDTRY
773 return ret;
776 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
777 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
778 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
780 LPCSTR pszObjId = pvStructInfo;
781 DWORD bytesNeeded = 0, lenBytes;
782 BOOL ret = TRUE;
783 int firstPos = 0;
784 BYTE firstByte = 0;
786 TRACE("%s\n", debugstr_a(pszObjId));
788 if (pszObjId)
790 const char *ptr;
791 int val1, val2;
793 if (sscanf(pszObjId, "%d.%d%n", &val1, &val2, &firstPos) != 2)
795 SetLastError(CRYPT_E_ASN1_ERROR);
796 return FALSE;
798 bytesNeeded++;
799 firstByte = val1 * 40 + val2;
800 ptr = pszObjId + firstPos;
801 if (*ptr == '.')
803 ptr++;
804 firstPos++;
806 while (ret && *ptr)
808 int pos;
810 /* note I assume each component is at most 32-bits long in base 2 */
811 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
813 if (val1 >= 0x10000000)
814 bytesNeeded += 5;
815 else if (val1 >= 0x200000)
816 bytesNeeded += 4;
817 else if (val1 >= 0x4000)
818 bytesNeeded += 3;
819 else if (val1 >= 0x80)
820 bytesNeeded += 2;
821 else
822 bytesNeeded += 1;
823 ptr += pos;
824 if (*ptr == '.')
825 ptr++;
827 else
829 SetLastError(CRYPT_E_ASN1_ERROR);
830 return FALSE;
833 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
835 else
836 lenBytes = 1;
837 bytesNeeded += 1 + lenBytes;
838 if (pbEncoded)
840 if (*pcbEncoded < bytesNeeded)
842 SetLastError(ERROR_MORE_DATA);
843 ret = FALSE;
845 else
847 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
848 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
849 pbEncoded += lenBytes;
850 if (pszObjId)
852 const char *ptr;
853 int val, pos;
855 *pbEncoded++ = firstByte;
856 ptr = pszObjId + firstPos;
857 while (ret && *ptr)
859 sscanf(ptr, "%d%n", &val, &pos);
861 unsigned char outBytes[5];
862 int numBytes, i;
864 if (val >= 0x10000000)
865 numBytes = 5;
866 else if (val >= 0x200000)
867 numBytes = 4;
868 else if (val >= 0x4000)
869 numBytes = 3;
870 else if (val >= 0x80)
871 numBytes = 2;
872 else
873 numBytes = 1;
874 for (i = numBytes; i > 0; i--)
876 outBytes[i - 1] = val & 0x7f;
877 val >>= 7;
879 for (i = 0; i < numBytes - 1; i++)
880 *pbEncoded++ = outBytes[i] | 0x80;
881 *pbEncoded++ = outBytes[i];
882 ptr += pos;
883 if (*ptr == '.')
884 ptr++;
890 *pcbEncoded = bytesNeeded;
891 return ret;
894 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
895 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
896 DWORD *pcbEncoded)
898 BOOL ret = TRUE;
899 LPCSTR str = (LPCSTR)value->Value.pbData;
900 DWORD bytesNeeded, lenBytes, encodedLen;
902 encodedLen = value->Value.cbData ? value->Value.cbData : strlen(str);
903 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
904 bytesNeeded = 1 + lenBytes + encodedLen;
905 if (!pbEncoded)
906 *pcbEncoded = bytesNeeded;
907 else
909 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
910 pbEncoded, pcbEncoded, bytesNeeded)))
912 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
913 pbEncoded = *(BYTE **)pbEncoded;
914 *pbEncoded++ = tag;
915 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
916 pbEncoded += lenBytes;
917 memcpy(pbEncoded, str, encodedLen);
920 return ret;
923 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
924 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
925 DWORD *pcbEncoded)
927 BOOL ret = TRUE;
928 LPCWSTR str = (LPCWSTR)value->Value.pbData;
929 DWORD bytesNeeded, lenBytes, strLen;
931 if (value->Value.cbData)
932 strLen = value->Value.cbData / sizeof(WCHAR);
933 else if (value->Value.pbData)
934 strLen = lstrlenW(str);
935 else
936 strLen = 0;
937 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
938 bytesNeeded = 1 + lenBytes + strLen * 2;
939 if (!pbEncoded)
940 *pcbEncoded = bytesNeeded;
941 else
943 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
944 pbEncoded, pcbEncoded, bytesNeeded)))
946 DWORD i;
948 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
949 pbEncoded = *(BYTE **)pbEncoded;
950 *pbEncoded++ = ASN_BMPSTRING;
951 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
952 pbEncoded += lenBytes;
953 for (i = 0; i < strLen; i++)
955 *pbEncoded++ = (str[i] & 0xff00) >> 8;
956 *pbEncoded++ = str[i] & 0x00ff;
960 return ret;
963 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
964 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
965 DWORD *pcbEncoded)
967 BOOL ret = TRUE;
968 LPCWSTR str = (LPCWSTR)value->Value.pbData;
969 DWORD bytesNeeded, lenBytes, encodedLen, strLen;
971 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
972 strlenW(str);
973 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
974 NULL);
975 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
976 bytesNeeded = 1 + lenBytes + encodedLen;
977 if (!pbEncoded)
978 *pcbEncoded = bytesNeeded;
979 else
981 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
982 pbEncoded, pcbEncoded, bytesNeeded)))
984 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
985 pbEncoded = *(BYTE **)pbEncoded;
986 *pbEncoded++ = ASN_UTF8STRING;
987 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
988 pbEncoded += lenBytes;
989 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
990 bytesNeeded - lenBytes - 1, NULL, NULL);
993 return ret;
996 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
997 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
998 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1000 BOOL ret = TRUE;
1002 __TRY
1004 const CERT_NAME_VALUE *value = pvStructInfo;
1006 switch (value->dwValueType)
1008 case CERT_RDN_ANY_TYPE:
1009 /* explicitly disallowed */
1010 SetLastError(E_INVALIDARG);
1011 ret = FALSE;
1012 break;
1013 case CERT_RDN_ENCODED_BLOB:
1014 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
1015 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1016 break;
1017 case CERT_RDN_OCTET_STRING:
1018 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1019 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1020 break;
1021 case CERT_RDN_NUMERIC_STRING:
1022 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1023 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1024 break;
1025 case CERT_RDN_PRINTABLE_STRING:
1026 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1027 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1028 break;
1029 case CERT_RDN_TELETEX_STRING:
1030 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1031 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1032 break;
1033 case CERT_RDN_VIDEOTEX_STRING:
1034 ret = CRYPT_AsnEncodeStringCoerce(value,
1035 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1036 break;
1037 case CERT_RDN_IA5_STRING:
1038 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1039 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1040 break;
1041 case CERT_RDN_GRAPHIC_STRING:
1042 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1043 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1044 break;
1045 case CERT_RDN_VISIBLE_STRING:
1046 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1047 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1048 break;
1049 case CERT_RDN_GENERAL_STRING:
1050 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1051 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1052 break;
1053 case CERT_RDN_UNIVERSAL_STRING:
1054 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1055 SetLastError(CRYPT_E_ASN1_CHOICE);
1056 ret = FALSE;
1057 break;
1058 case CERT_RDN_BMP_STRING:
1059 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1060 pbEncoded, pcbEncoded);
1061 break;
1062 case CERT_RDN_UTF8_STRING:
1063 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1064 pbEncoded, pcbEncoded);
1065 break;
1066 default:
1067 SetLastError(CRYPT_E_ASN1_CHOICE);
1068 ret = FALSE;
1071 __EXCEPT_PAGE_FAULT
1073 SetLastError(STATUS_ACCESS_VIOLATION);
1074 ret = FALSE;
1076 __ENDTRY
1077 return ret;
1080 static BOOL CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1081 CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1082 BYTE *pbEncoded, DWORD *pcbEncoded)
1084 DWORD bytesNeeded = 0, lenBytes, size;
1085 BOOL ret;
1087 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1088 0, NULL, NULL, &size);
1089 if (ret)
1091 bytesNeeded += size;
1092 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1093 * with dwValueType, so "cast" it to get its encoded size
1095 ret = nameValueEncodeFunc(dwCertEncodingType, NULL, &attr->dwValueType,
1096 0, NULL, NULL, &size);
1097 if (ret)
1099 bytesNeeded += size;
1100 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1101 bytesNeeded += 1 + lenBytes;
1102 if (pbEncoded)
1104 if (*pcbEncoded < bytesNeeded)
1106 SetLastError(ERROR_MORE_DATA);
1107 ret = FALSE;
1109 else
1111 *pbEncoded++ = ASN_SEQUENCE;
1112 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1113 &lenBytes);
1114 pbEncoded += lenBytes;
1115 size = bytesNeeded - 1 - lenBytes;
1116 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1117 attr->pszObjId, 0, NULL, pbEncoded, &size);
1118 if (ret)
1120 pbEncoded += size;
1121 size = bytesNeeded - 1 - lenBytes - size;
1122 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1123 &attr->dwValueType, 0, NULL, pbEncoded, &size);
1124 if (!ret)
1125 *pcbEncoded = size;
1129 if (ret)
1130 *pcbEncoded = bytesNeeded;
1132 else
1134 /* Have to propagate index of failing character */
1135 *pcbEncoded = size;
1138 return ret;
1141 static int BLOBComp(const void *l, const void *r)
1143 const CRYPT_DER_BLOB *a = l, *b = r;
1144 int ret;
1146 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1147 ret = a->cbData - b->cbData;
1148 return ret;
1151 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1153 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1154 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1155 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1157 const CRYPT_BLOB_ARRAY *set = pvStructInfo;
1158 DWORD bytesNeeded = 0, lenBytes, i;
1159 BOOL ret;
1161 for (i = 0; i < set->cBlob; i++)
1162 bytesNeeded += set->rgBlob[i].cbData;
1163 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1164 bytesNeeded += 1 + lenBytes;
1165 if (!pbEncoded)
1167 *pcbEncoded = bytesNeeded;
1168 ret = TRUE;
1170 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1171 pbEncoded, pcbEncoded, bytesNeeded)))
1173 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1174 pbEncoded = *(BYTE **)pbEncoded;
1175 qsort(set->rgBlob, set->cBlob, sizeof(CRYPT_DER_BLOB), BLOBComp);
1176 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1177 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1178 pbEncoded += lenBytes;
1179 for (i = 0; ret && i < set->cBlob; i++)
1181 memcpy(pbEncoded, set->rgBlob[i].pbData, set->rgBlob[i].cbData);
1182 pbEncoded += set->rgBlob[i].cbData;
1185 return ret;
1188 struct DERSetDescriptor
1190 DWORD cItems;
1191 const void *items;
1192 size_t itemSize;
1193 size_t itemOffset;
1194 CryptEncodeObjectExFunc encode;
1197 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,
1198 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1199 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1201 const struct DERSetDescriptor *desc = pvStructInfo;
1202 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1203 BOOL ret = TRUE;
1204 DWORD i;
1206 if (desc->cItems)
1208 setOf.rgBlob = CryptMemAlloc(desc->cItems * sizeof(CRYPT_DER_BLOB));
1209 if (!setOf.rgBlob)
1210 ret = FALSE;
1211 else
1213 setOf.cBlob = desc->cItems;
1214 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1217 for (i = 0; ret && i < setOf.cBlob; i++)
1219 ret = desc->encode(dwCertEncodingType, lpszStructType,
1220 (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
1221 0, NULL, NULL, &setOf.rgBlob[i].cbData);
1222 if (ret)
1224 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1225 if (!setOf.rgBlob[i].pbData)
1226 ret = FALSE;
1227 else
1228 ret = desc->encode(dwCertEncodingType, lpszStructType,
1229 (const BYTE *)desc->items + i * desc->itemSize +
1230 desc->itemOffset, 0, NULL, setOf.rgBlob[i].pbData,
1231 &setOf.rgBlob[i].cbData);
1233 /* Some functions propagate their errors through the size */
1234 if (!ret)
1235 *pcbEncoded = setOf.rgBlob[i].cbData;
1237 if (ret)
1239 DWORD bytesNeeded = 0, lenBytes;
1241 for (i = 0; i < setOf.cBlob; i++)
1242 bytesNeeded += setOf.rgBlob[i].cbData;
1243 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1244 bytesNeeded += 1 + lenBytes;
1245 if (!pbEncoded)
1246 *pcbEncoded = bytesNeeded;
1247 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1248 pbEncoded, pcbEncoded, bytesNeeded)))
1250 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1251 pbEncoded = *(BYTE **)pbEncoded;
1252 qsort(setOf.rgBlob, setOf.cBlob, sizeof(CRYPT_DER_BLOB),
1253 BLOBComp);
1254 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1255 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1256 pbEncoded += lenBytes;
1257 for (i = 0; i < setOf.cBlob; i++)
1259 memcpy(pbEncoded, setOf.rgBlob[i].pbData,
1260 setOf.rgBlob[i].cbData);
1261 pbEncoded += setOf.rgBlob[i].cbData;
1265 for (i = 0; i < setOf.cBlob; i++)
1266 CryptMemFree(setOf.rgBlob[i].pbData);
1267 CryptMemFree(setOf.rgBlob);
1268 return ret;
1271 static BOOL CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
1272 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1273 DWORD *pcbEncoded)
1275 BOOL ret;
1276 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1278 __TRY
1280 DWORD i;
1282 ret = TRUE;
1283 if (rdn->cRDNAttr)
1285 setOf.cBlob = rdn->cRDNAttr;
1286 setOf.rgBlob = CryptMemAlloc(rdn->cRDNAttr *
1287 sizeof(CRYPT_DER_BLOB));
1288 if (!setOf.rgBlob)
1289 ret = FALSE;
1290 else
1291 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1293 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1295 setOf.rgBlob[i].cbData = 0;
1296 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1297 nameValueEncodeFunc, NULL, &setOf.rgBlob[i].cbData);
1298 if (ret)
1300 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1301 if (!setOf.rgBlob[i].pbData)
1302 ret = FALSE;
1303 else
1304 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1305 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1306 setOf.rgBlob[i].pbData, &setOf.rgBlob[i].cbData);
1308 if (!ret)
1310 /* Have to propagate index of failing character */
1311 *pcbEncoded = setOf.rgBlob[i].cbData;
1314 if (ret)
1315 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1316 pbEncoded, pcbEncoded);
1317 for (i = 0; i < setOf.cBlob; i++)
1318 CryptMemFree(setOf.rgBlob[i].pbData);
1320 __EXCEPT_PAGE_FAULT
1322 SetLastError(STATUS_ACCESS_VIOLATION);
1323 ret = FALSE;
1325 __ENDTRY
1326 CryptMemFree(setOf.rgBlob);
1327 return ret;
1330 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1331 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1332 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1334 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1335 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1336 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1337 DWORD *pcbEncoded)
1339 const CERT_NAME_VALUE *value = pvStructInfo;
1340 BOOL ret;
1342 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1343 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1344 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1345 else
1346 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1347 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1348 return ret;
1351 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1352 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1353 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1355 BOOL ret = TRUE;
1357 __TRY
1359 const CERT_NAME_INFO *info = pvStructInfo;
1360 DWORD bytesNeeded = 0, lenBytes, size, i;
1362 TRACE("encoding name with %d RDNs\n", info->cRDN);
1363 ret = TRUE;
1364 for (i = 0; ret && i < info->cRDN; i++)
1366 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1367 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1368 if (ret)
1369 bytesNeeded += size;
1370 else
1371 *pcbEncoded = size;
1373 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1374 bytesNeeded += 1 + lenBytes;
1375 if (ret)
1377 if (!pbEncoded)
1378 *pcbEncoded = bytesNeeded;
1379 else
1381 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1382 pbEncoded, pcbEncoded, bytesNeeded)))
1384 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1385 pbEncoded = *(BYTE **)pbEncoded;
1386 *pbEncoded++ = ASN_SEQUENCEOF;
1387 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1388 &lenBytes);
1389 pbEncoded += lenBytes;
1390 for (i = 0; ret && i < info->cRDN; i++)
1392 size = bytesNeeded;
1393 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1394 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1395 pbEncoded, &size);
1396 if (ret)
1398 pbEncoded += size;
1399 bytesNeeded -= size;
1401 else
1402 *pcbEncoded = size;
1408 __EXCEPT_PAGE_FAULT
1410 SetLastError(STATUS_ACCESS_VIOLATION);
1411 ret = FALSE;
1413 __ENDTRY
1414 return ret;
1417 static BOOL WINAPI CRYPT_AsnEncodeCTLVersion(DWORD dwCertEncodingType,
1418 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1419 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1421 const DWORD *ver = pvStructInfo;
1422 BOOL ret;
1424 /* CTL_V1 is not encoded */
1425 if (*ver == CTL_V1)
1427 *pcbEncoded = 0;
1428 ret = TRUE;
1430 else
1431 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
1432 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1433 return ret;
1436 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
1437 * if they are empty and the OID is not empty (otherwise omits them.)
1439 static BOOL WINAPI CRYPT_AsnEncodeCTLSubjectAlgorithm(
1440 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1441 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1442 DWORD *pcbEncoded)
1444 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
1445 BOOL ret;
1446 struct AsnEncodeSequenceItem items[2] = {
1447 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
1449 DWORD cItem = 1;
1451 if (algo->pszObjId)
1453 static const BYTE asn1Null[] = { ASN_NULL, 0 };
1454 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
1455 (LPBYTE)asn1Null };
1457 if (algo->Parameters.cbData)
1458 items[cItem].pvStructInfo = &algo->Parameters;
1459 else
1460 items[cItem].pvStructInfo = &nullBlob;
1461 items[cItem].encodeFunc = CRYPT_CopyEncodedBlob;
1462 cItem++;
1464 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1465 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1466 return ret;
1469 static BOOL CRYPT_AsnEncodeCTLEntry(const CTL_ENTRY *entry,
1470 BYTE *pbEncoded, DWORD *pcbEncoded)
1472 struct AsnEncodeSequenceItem items[2] = {
1473 { &entry->SubjectIdentifier, CRYPT_AsnEncodeOctets, 0 },
1474 { &entry->cAttribute, CRYPT_AsnEncodePKCSAttributes, 0 },
1476 BOOL ret;
1478 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1479 sizeof(items) / sizeof(items[0]), 0, NULL, pbEncoded, pcbEncoded);
1480 return ret;
1483 struct CTLEntries
1485 DWORD cEntry;
1486 CTL_ENTRY *rgEntry;
1489 static BOOL WINAPI CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType,
1490 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1491 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1493 BOOL ret;
1494 DWORD bytesNeeded, dataLen, lenBytes, i;
1495 const struct CTLEntries *entries = pvStructInfo;
1497 ret = TRUE;
1498 for (i = 0, dataLen = 0; ret && i < entries->cEntry; i++)
1500 DWORD size;
1502 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i], NULL, &size);
1503 if (ret)
1504 dataLen += size;
1506 if (ret)
1508 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1509 bytesNeeded = 1 + lenBytes + dataLen;
1510 if (!pbEncoded)
1511 *pcbEncoded = bytesNeeded;
1512 else
1514 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1515 pbEncoded, pcbEncoded, bytesNeeded)))
1517 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1518 pbEncoded = *(BYTE **)pbEncoded;
1519 *pbEncoded++ = ASN_SEQUENCEOF;
1520 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1521 pbEncoded += lenBytes;
1522 for (i = 0; ret && i < entries->cEntry; i++)
1524 DWORD size = dataLen;
1526 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i],
1527 pbEncoded, &size);
1528 pbEncoded += size;
1529 dataLen -= size;
1534 return ret;
1537 static BOOL WINAPI CRYPT_AsnEncodeCTL(DWORD dwCertEncodingType,
1538 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1539 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1541 BOOL ret = FALSE;
1543 __TRY
1545 const CTL_INFO *info = pvStructInfo;
1546 struct AsnEncodeSequenceItem items[9] = {
1547 { &info->dwVersion, CRYPT_AsnEncodeCTLVersion, 0 },
1548 { &info->SubjectUsage, CRYPT_AsnEncodeEnhancedKeyUsage, 0 },
1550 struct AsnConstructedItem constructed = { 0 };
1551 DWORD cItem = 2;
1553 if (info->ListIdentifier.cbData)
1555 items[cItem].pvStructInfo = &info->ListIdentifier;
1556 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
1557 cItem++;
1559 if (info->SequenceNumber.cbData)
1561 items[cItem].pvStructInfo = &info->SequenceNumber;
1562 items[cItem].encodeFunc = CRYPT_AsnEncodeInteger;
1563 cItem++;
1565 items[cItem].pvStructInfo = &info->ThisUpdate;
1566 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1567 cItem++;
1568 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
1570 items[cItem].pvStructInfo = &info->NextUpdate;
1571 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1572 cItem++;
1574 items[cItem].pvStructInfo = &info->SubjectAlgorithm;
1575 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLSubjectAlgorithm;
1576 cItem++;
1577 if (info->cCTLEntry)
1579 items[cItem].pvStructInfo = &info->cCTLEntry;
1580 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLEntries;
1581 cItem++;
1583 if (info->cExtension)
1585 constructed.tag = 0;
1586 constructed.pvStructInfo = &info->cExtension;
1587 constructed.encodeFunc = CRYPT_AsnEncodeExtensions;
1588 items[cItem].pvStructInfo = &constructed;
1589 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1590 cItem++;
1592 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1593 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1595 __EXCEPT_PAGE_FAULT
1597 SetLastError(STATUS_ACCESS_VIOLATION);
1599 __ENDTRY
1600 return ret;
1603 static BOOL CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType,
1604 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1605 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1607 BOOL ret = FALSE;
1609 __TRY
1611 const CRYPT_SMIME_CAPABILITY *capability = pvStructInfo;
1613 if (!capability->pszObjId)
1614 SetLastError(E_INVALIDARG);
1615 else
1617 struct AsnEncodeSequenceItem items[] = {
1618 { capability->pszObjId, CRYPT_AsnEncodeOid, 0 },
1619 { &capability->Parameters, CRYPT_CopyEncodedBlob, 0 },
1622 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1623 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1624 pcbEncoded);
1627 __EXCEPT_PAGE_FAULT
1629 SetLastError(STATUS_ACCESS_VIOLATION);
1631 __ENDTRY
1632 return ret;
1635 static BOOL WINAPI CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType,
1636 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1637 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1639 BOOL ret = FALSE;
1641 __TRY
1643 DWORD bytesNeeded, dataLen, lenBytes, i;
1644 const CRYPT_SMIME_CAPABILITIES *capabilities = pvStructInfo;
1646 ret = TRUE;
1647 for (i = 0, dataLen = 0; ret && i < capabilities->cCapability; i++)
1649 DWORD size;
1651 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType, NULL,
1652 &capabilities->rgCapability[i], 0, NULL, NULL, &size);
1653 if (ret)
1654 dataLen += size;
1656 if (ret)
1658 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1659 bytesNeeded = 1 + lenBytes + dataLen;
1660 if (!pbEncoded)
1661 *pcbEncoded = bytesNeeded;
1662 else
1664 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1665 pbEncoded, pcbEncoded, bytesNeeded)))
1667 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1668 pbEncoded = *(BYTE **)pbEncoded;
1669 *pbEncoded++ = ASN_SEQUENCEOF;
1670 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1671 pbEncoded += lenBytes;
1672 for (i = 0; i < capabilities->cCapability; i++)
1674 DWORD size = dataLen;
1676 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType,
1677 NULL, &capabilities->rgCapability[i], 0, NULL,
1678 pbEncoded, &size);
1679 pbEncoded += size;
1680 dataLen -= size;
1686 __EXCEPT_PAGE_FAULT
1688 SetLastError(STATUS_ACCESS_VIOLATION);
1690 __ENDTRY
1691 return ret;
1694 static BOOL WINAPI CRYPT_AsnEncodeNoticeNumbers(DWORD dwCertEncodingType,
1695 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1696 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1698 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
1699 DWORD bytesNeeded, dataLen, lenBytes, i;
1700 BOOL ret = TRUE;
1702 for (i = 0, dataLen = 0; ret && i < noticeRef->cNoticeNumbers; i++)
1704 DWORD size;
1706 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
1707 &noticeRef->rgNoticeNumbers[i], 0, NULL, NULL, &size);
1708 if (ret)
1709 dataLen += size;
1711 if (ret)
1713 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1714 bytesNeeded = 1 + lenBytes + dataLen;
1715 if (!pbEncoded)
1716 *pcbEncoded = bytesNeeded;
1717 else
1719 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1720 pcbEncoded, bytesNeeded)))
1722 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1723 pbEncoded = *(BYTE **)pbEncoded;
1724 *pbEncoded++ = ASN_SEQUENCE;
1725 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1726 pbEncoded += lenBytes;
1727 for (i = 0; i < noticeRef->cNoticeNumbers; i++)
1729 DWORD size = dataLen;
1731 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
1732 &noticeRef->rgNoticeNumbers[i], 0, NULL, pbEncoded, &size);
1733 pbEncoded += size;
1734 dataLen -= size;
1739 return ret;
1742 static BOOL WINAPI CRYPT_AsnEncodeNoticeReference(DWORD dwCertEncodingType,
1743 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1744 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1746 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
1747 BOOL ret;
1748 CERT_NAME_VALUE orgValue = { CERT_RDN_IA5_STRING,
1749 { 0, (LPBYTE)noticeRef->pszOrganization } };
1750 struct AsnEncodeSequenceItem items[] = {
1751 { &orgValue, CRYPT_AsnEncodeNameValue, 0 },
1752 { noticeRef, CRYPT_AsnEncodeNoticeNumbers, 0 },
1755 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1756 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1757 pcbEncoded);
1758 return ret;
1761 static BOOL WINAPI CRYPT_AsnEncodePolicyQualifierUserNotice(
1762 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1763 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1764 DWORD *pcbEncoded)
1766 BOOL ret = FALSE;
1768 __TRY
1770 const CERT_POLICY_QUALIFIER_USER_NOTICE *notice = pvStructInfo;
1771 struct AsnEncodeSequenceItem items[2];
1772 CERT_NAME_VALUE displayTextValue;
1773 DWORD cItem = 0;
1775 ret = TRUE;
1776 if (notice->pNoticeReference)
1778 items[cItem].encodeFunc = CRYPT_AsnEncodeNoticeReference;
1779 items[cItem].pvStructInfo = notice->pNoticeReference;
1780 cItem++;
1782 if (notice->pszDisplayText)
1784 displayTextValue.dwValueType = CERT_RDN_BMP_STRING;
1785 displayTextValue.Value.cbData = 0;
1786 displayTextValue.Value.pbData = (LPBYTE)notice->pszDisplayText;
1787 items[cItem].encodeFunc = CRYPT_AsnEncodeNameValue;
1788 items[cItem].pvStructInfo = &displayTextValue;
1789 cItem++;
1791 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1792 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1794 __EXCEPT_PAGE_FAULT
1796 SetLastError(STATUS_ACCESS_VIOLATION);
1798 __ENDTRY
1799 return ret;
1802 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1803 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1804 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1806 BOOL ret = FALSE;
1808 __TRY
1810 const CRYPT_ATTRIBUTE *attr = pvStructInfo;
1812 if (!attr->pszObjId)
1813 SetLastError(E_INVALIDARG);
1814 else
1816 struct AsnEncodeSequenceItem items[2] = {
1817 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1818 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1821 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1822 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1823 pcbEncoded);
1826 __EXCEPT_PAGE_FAULT
1828 SetLastError(STATUS_ACCESS_VIOLATION);
1830 __ENDTRY
1831 return ret;
1834 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1835 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1836 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1838 BOOL ret = FALSE;
1840 __TRY
1842 const CRYPT_ATTRIBUTES *attributes = pvStructInfo;
1843 struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
1844 sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
1846 ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
1847 &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1849 __EXCEPT_PAGE_FAULT
1851 SetLastError(STATUS_ACCESS_VIOLATION);
1853 __ENDTRY
1854 return ret;
1857 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1858 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
1859 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1860 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1861 DWORD *pcbEncoded)
1863 const CRYPT_CONTENT_INFO *info = pvStructInfo;
1864 struct AsnEncodeSequenceItem items[2] = {
1865 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1866 { NULL, NULL, 0 },
1868 struct AsnConstructedItem constructed = { 0 };
1869 DWORD cItem = 1;
1871 if (info->Content.cbData)
1873 constructed.tag = 0;
1874 constructed.pvStructInfo = &info->Content;
1875 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1876 items[cItem].pvStructInfo = &constructed;
1877 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1878 cItem++;
1880 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1881 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1884 BOOL CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA *digestedData,
1885 void *pvData, DWORD *pcbData)
1887 struct AsnEncodeSequenceItem items[] = {
1888 { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1889 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
1890 0 },
1891 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1892 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1895 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1896 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
1899 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1900 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1901 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1903 BOOL ret = FALSE;
1905 __TRY
1907 const CRYPT_CONTENT_INFO *info = pvStructInfo;
1909 if (!info->pszObjId)
1910 SetLastError(E_INVALIDARG);
1911 else
1912 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
1913 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1914 pcbEncoded);
1916 __EXCEPT_PAGE_FAULT
1918 SetLastError(STATUS_ACCESS_VIOLATION);
1920 __ENDTRY
1921 return ret;
1924 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1925 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1926 DWORD *pcbEncoded)
1928 BOOL ret = TRUE;
1929 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1930 DWORD bytesNeeded, lenBytes, encodedLen;
1932 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1933 strlenW(str);
1934 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1935 bytesNeeded = 1 + lenBytes + encodedLen;
1936 if (!pbEncoded)
1937 *pcbEncoded = bytesNeeded;
1938 else
1940 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1941 pbEncoded, pcbEncoded, bytesNeeded)))
1943 DWORD i;
1945 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1946 pbEncoded = *(BYTE **)pbEncoded;
1947 *pbEncoded++ = tag;
1948 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1949 pbEncoded += lenBytes;
1950 for (i = 0; i < encodedLen; i++)
1951 *pbEncoded++ = (BYTE)str[i];
1954 return ret;
1957 static void CRYPT_FreeSpace(PCRYPT_ENCODE_PARA pEncodePara, LPVOID pv)
1959 if (pEncodePara && pEncodePara->pfnFree)
1960 pEncodePara->pfnFree(pv);
1961 else
1962 LocalFree(pv);
1965 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
1966 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1967 DWORD *pcbEncoded)
1969 BOOL ret = TRUE;
1970 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1971 DWORD bytesNeeded, lenBytes, encodedLen;
1973 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1974 strlenW(str);
1975 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1976 bytesNeeded = 1 + lenBytes + encodedLen;
1977 if (!pbEncoded)
1978 *pcbEncoded = bytesNeeded;
1979 else
1981 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1982 pbEncoded, pcbEncoded, bytesNeeded)))
1984 DWORD i;
1985 BYTE *ptr;
1987 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1988 ptr = *(BYTE **)pbEncoded;
1989 else
1990 ptr = pbEncoded;
1991 *ptr++ = ASN_NUMERICSTRING;
1992 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
1993 ptr += lenBytes;
1994 for (i = 0; ret && i < encodedLen; i++)
1996 if (isdigitW(str[i]))
1997 *ptr++ = (BYTE)str[i];
1998 else
2000 *pcbEncoded = i;
2001 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
2002 ret = FALSE;
2005 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2006 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2009 return ret;
2012 static inline int isprintableW(WCHAR wc)
2014 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
2015 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
2016 wc == '/' || wc == ':' || wc == '=' || wc == '?';
2019 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
2020 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
2021 DWORD *pcbEncoded)
2023 BOOL ret = TRUE;
2024 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2025 DWORD bytesNeeded, lenBytes, encodedLen;
2027 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
2028 strlenW(str);
2029 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2030 bytesNeeded = 1 + lenBytes + encodedLen;
2031 if (!pbEncoded)
2032 *pcbEncoded = bytesNeeded;
2033 else
2035 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2036 pbEncoded, pcbEncoded, bytesNeeded)))
2038 DWORD i;
2039 BYTE *ptr;
2041 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2042 ptr = *(BYTE **)pbEncoded;
2043 else
2044 ptr = pbEncoded;
2045 *ptr++ = ASN_PRINTABLESTRING;
2046 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2047 ptr += lenBytes;
2048 for (i = 0; ret && i < encodedLen; i++)
2050 if (isprintableW(str[i]))
2051 *ptr++ = (BYTE)str[i];
2052 else
2054 *pcbEncoded = i;
2055 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
2056 ret = FALSE;
2059 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2060 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2063 return ret;
2066 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
2067 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
2068 DWORD *pcbEncoded)
2070 BOOL ret = TRUE;
2071 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2072 DWORD bytesNeeded, lenBytes, encodedLen;
2074 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
2075 strlenW(str);
2076 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2077 bytesNeeded = 1 + lenBytes + encodedLen;
2078 if (!pbEncoded)
2079 *pcbEncoded = bytesNeeded;
2080 else
2082 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2083 pbEncoded, pcbEncoded, bytesNeeded)))
2085 DWORD i;
2086 BYTE *ptr;
2088 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2089 ptr = *(BYTE **)pbEncoded;
2090 else
2091 ptr = pbEncoded;
2092 *ptr++ = ASN_IA5STRING;
2093 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2094 ptr += lenBytes;
2095 for (i = 0; ret && i < encodedLen; i++)
2097 if (str[i] <= 0x7f)
2098 *ptr++ = (BYTE)str[i];
2099 else
2101 *pcbEncoded = i;
2102 SetLastError(CRYPT_E_INVALID_IA5_STRING);
2103 ret = FALSE;
2106 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2107 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2110 return ret;
2113 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
2114 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
2115 DWORD *pcbEncoded)
2117 BOOL ret = TRUE;
2118 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2119 DWORD bytesNeeded, lenBytes, strLen;
2121 /* FIXME: doesn't handle composite characters */
2122 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
2123 strlenW(str);
2124 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
2125 bytesNeeded = 1 + lenBytes + strLen * 4;
2126 if (!pbEncoded)
2127 *pcbEncoded = bytesNeeded;
2128 else
2130 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2131 pbEncoded, pcbEncoded, bytesNeeded)))
2133 DWORD i;
2135 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2136 pbEncoded = *(BYTE **)pbEncoded;
2137 *pbEncoded++ = ASN_UNIVERSALSTRING;
2138 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
2139 pbEncoded += lenBytes;
2140 for (i = 0; i < strLen; i++)
2142 *pbEncoded++ = 0;
2143 *pbEncoded++ = 0;
2144 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
2145 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
2149 return ret;
2152 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
2153 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2154 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2156 BOOL ret = FALSE;
2158 __TRY
2160 const CERT_NAME_VALUE *value = pvStructInfo;
2162 switch (value->dwValueType)
2164 case CERT_RDN_ANY_TYPE:
2165 case CERT_RDN_ENCODED_BLOB:
2166 case CERT_RDN_OCTET_STRING:
2167 SetLastError(CRYPT_E_NOT_CHAR_STRING);
2168 break;
2169 case CERT_RDN_NUMERIC_STRING:
2170 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
2171 pbEncoded, pcbEncoded);
2172 break;
2173 case CERT_RDN_PRINTABLE_STRING:
2174 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
2175 pbEncoded, pcbEncoded);
2176 break;
2177 case CERT_RDN_TELETEX_STRING:
2178 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
2179 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2180 break;
2181 case CERT_RDN_VIDEOTEX_STRING:
2182 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
2183 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2184 break;
2185 case CERT_RDN_IA5_STRING:
2186 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
2187 pbEncoded, pcbEncoded);
2188 break;
2189 case CERT_RDN_GRAPHIC_STRING:
2190 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
2191 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2192 break;
2193 case CERT_RDN_VISIBLE_STRING:
2194 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
2195 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2196 break;
2197 case CERT_RDN_GENERAL_STRING:
2198 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
2199 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2200 break;
2201 case CERT_RDN_UNIVERSAL_STRING:
2202 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
2203 pbEncoded, pcbEncoded);
2204 break;
2205 case CERT_RDN_BMP_STRING:
2206 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
2207 pbEncoded, pcbEncoded);
2208 break;
2209 case CERT_RDN_UTF8_STRING:
2210 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
2211 pbEncoded, pcbEncoded);
2212 break;
2213 default:
2214 SetLastError(CRYPT_E_ASN1_CHOICE);
2217 __EXCEPT_PAGE_FAULT
2219 SetLastError(STATUS_ACCESS_VIOLATION);
2221 __ENDTRY
2222 return ret;
2225 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
2226 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2227 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2229 BOOL ret;
2231 __TRY
2233 const CERT_NAME_INFO *info = pvStructInfo;
2234 DWORD bytesNeeded = 0, lenBytes, size, i;
2236 TRACE("encoding name with %d RDNs\n", info->cRDN);
2237 ret = TRUE;
2238 for (i = 0; ret && i < info->cRDN; i++)
2240 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
2241 CRYPT_AsnEncodeNameValue, NULL, &size);
2242 if (ret)
2243 bytesNeeded += size;
2245 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2246 bytesNeeded += 1 + lenBytes;
2247 if (ret)
2249 if (!pbEncoded)
2250 *pcbEncoded = bytesNeeded;
2251 else
2253 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2254 pbEncoded, pcbEncoded, bytesNeeded)))
2256 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2257 pbEncoded = *(BYTE **)pbEncoded;
2258 *pbEncoded++ = ASN_SEQUENCEOF;
2259 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
2260 &lenBytes);
2261 pbEncoded += lenBytes;
2262 for (i = 0; ret && i < info->cRDN; i++)
2264 size = bytesNeeded;
2265 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
2266 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, pbEncoded,
2267 &size);
2268 if (ret)
2270 pbEncoded += size;
2271 bytesNeeded -= size;
2278 __EXCEPT_PAGE_FAULT
2280 SetLastError(STATUS_ACCESS_VIOLATION);
2281 ret = FALSE;
2283 __ENDTRY
2284 return ret;
2287 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
2288 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2289 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2291 BOOL val = *(const BOOL *)pvStructInfo, ret;
2293 TRACE("%d\n", val);
2295 if (!pbEncoded)
2297 *pcbEncoded = 3;
2298 ret = TRUE;
2300 else if (*pcbEncoded < 3)
2302 *pcbEncoded = 3;
2303 SetLastError(ERROR_MORE_DATA);
2304 ret = FALSE;
2306 else
2308 *pcbEncoded = 3;
2309 *pbEncoded++ = ASN_BOOL;
2310 *pbEncoded++ = 1;
2311 *pbEncoded++ = val ? 0xff : 0;
2312 ret = TRUE;
2314 TRACE("returning %d (%08x)\n", ret, GetLastError());
2315 return ret;
2318 static BOOL WINAPI CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType,
2319 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2320 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2322 const CERT_ALT_NAME_ENTRY *entry = pvStructInfo;
2323 BOOL ret;
2324 DWORD dataLen;
2325 BYTE tag;
2327 ret = TRUE;
2328 switch (entry->dwAltNameChoice)
2330 case CERT_ALT_NAME_RFC822_NAME:
2331 case CERT_ALT_NAME_DNS_NAME:
2332 case CERT_ALT_NAME_URL:
2333 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2334 if (entry->u.pwszURL)
2336 DWORD i;
2338 /* Not + 1: don't encode the NULL-terminator */
2339 dataLen = lstrlenW(entry->u.pwszURL);
2340 for (i = 0; ret && i < dataLen; i++)
2342 if (entry->u.pwszURL[i] > 0x7f)
2344 SetLastError(CRYPT_E_INVALID_IA5_STRING);
2345 ret = FALSE;
2346 *pcbEncoded = i;
2350 else
2351 dataLen = 0;
2352 break;
2353 case CERT_ALT_NAME_DIRECTORY_NAME:
2354 tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1);
2355 dataLen = entry->u.DirectoryName.cbData;
2356 break;
2357 case CERT_ALT_NAME_IP_ADDRESS:
2358 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2359 dataLen = entry->u.IPAddress.cbData;
2360 break;
2361 case CERT_ALT_NAME_REGISTERED_ID:
2363 struct AsnEncodeTagSwappedItem swapped =
2364 { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID,
2365 CRYPT_AsnEncodeOid };
2367 return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded,
2368 pcbEncoded);
2370 case CERT_ALT_NAME_OTHER_NAME:
2371 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
2372 return FALSE;
2373 default:
2374 SetLastError(E_INVALIDARG);
2375 return FALSE;
2377 if (ret)
2379 DWORD bytesNeeded, lenBytes;
2381 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2382 bytesNeeded = 1 + dataLen + lenBytes;
2383 if (!pbEncoded)
2384 *pcbEncoded = bytesNeeded;
2385 else if (*pcbEncoded < bytesNeeded)
2387 SetLastError(ERROR_MORE_DATA);
2388 *pcbEncoded = bytesNeeded;
2389 ret = FALSE;
2391 else
2393 *pbEncoded++ = tag;
2394 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2395 pbEncoded += lenBytes;
2396 switch (entry->dwAltNameChoice)
2398 case CERT_ALT_NAME_RFC822_NAME:
2399 case CERT_ALT_NAME_DNS_NAME:
2400 case CERT_ALT_NAME_URL:
2402 DWORD i;
2404 for (i = 0; i < dataLen; i++)
2405 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
2406 break;
2408 case CERT_ALT_NAME_DIRECTORY_NAME:
2409 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen);
2410 break;
2411 case CERT_ALT_NAME_IP_ADDRESS:
2412 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
2413 break;
2415 if (ret)
2416 *pcbEncoded = bytesNeeded;
2419 TRACE("returning %d (%08x)\n", ret, GetLastError());
2420 return ret;
2423 static BOOL WINAPI CRYPT_AsnEncodeIntegerSwapBytes(DWORD dwCertEncodingType,
2424 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2425 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2427 BOOL ret;
2429 __TRY
2431 const CRYPT_DATA_BLOB *blob = pvStructInfo;
2432 CRYPT_DATA_BLOB newBlob = { blob->cbData, NULL };
2434 ret = TRUE;
2435 if (newBlob.cbData)
2437 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2438 if (newBlob.pbData)
2440 DWORD i;
2442 for (i = 0; i < newBlob.cbData; i++)
2443 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2445 else
2446 ret = FALSE;
2448 if (ret)
2449 ret = CRYPT_AsnEncodeInteger(dwCertEncodingType, lpszStructType,
2450 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2451 CryptMemFree(newBlob.pbData);
2453 __EXCEPT_PAGE_FAULT
2455 SetLastError(STATUS_ACCESS_VIOLATION);
2456 ret = FALSE;
2458 __ENDTRY
2459 return ret;
2462 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
2463 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2464 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2466 BOOL ret;
2468 __TRY
2470 const CERT_AUTHORITY_KEY_ID_INFO *info = pvStructInfo;
2471 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2472 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2473 struct AsnConstructedItem constructed = { 0 };
2474 DWORD cItem = 0, cSwapped = 0;
2476 if (info->KeyId.cbData)
2478 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2479 swapped[cSwapped].pvStructInfo = &info->KeyId;
2480 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2481 items[cItem].pvStructInfo = &swapped[cSwapped];
2482 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2483 cSwapped++;
2484 cItem++;
2486 if (info->CertIssuer.cbData)
2488 constructed.tag = 1;
2489 constructed.pvStructInfo = &info->CertIssuer;
2490 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2491 items[cItem].pvStructInfo = &constructed;
2492 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2493 cItem++;
2495 if (info->CertSerialNumber.cbData)
2497 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2498 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2499 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2500 items[cItem].pvStructInfo = &swapped[cSwapped];
2501 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2502 cSwapped++;
2503 cItem++;
2505 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2506 pEncodePara, pbEncoded, pcbEncoded);
2508 __EXCEPT_PAGE_FAULT
2510 SetLastError(STATUS_ACCESS_VIOLATION);
2511 ret = FALSE;
2513 __ENDTRY
2514 return ret;
2517 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2518 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2519 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2521 BOOL ret;
2523 __TRY
2525 const CERT_ALT_NAME_INFO *info = pvStructInfo;
2526 DWORD bytesNeeded, dataLen, lenBytes, i;
2528 ret = TRUE;
2529 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2530 * can't encode an erroneous entry index if it's bigger than this.
2532 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2534 DWORD len;
2536 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, NULL,
2537 &info->rgAltEntry[i], 0, NULL, NULL, &len);
2538 if (ret)
2539 dataLen += len;
2540 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2542 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2543 * the bad character, now set the index of the bad
2544 * entry
2546 *pcbEncoded = (BYTE)i <<
2547 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2550 if (ret)
2552 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2553 bytesNeeded = 1 + lenBytes + dataLen;
2554 if (!pbEncoded)
2556 *pcbEncoded = bytesNeeded;
2557 ret = TRUE;
2559 else
2561 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2562 pbEncoded, pcbEncoded, bytesNeeded)))
2564 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2565 pbEncoded = *(BYTE **)pbEncoded;
2566 *pbEncoded++ = ASN_SEQUENCEOF;
2567 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2568 pbEncoded += lenBytes;
2569 for (i = 0; ret && i < info->cAltEntry; i++)
2571 DWORD len = dataLen;
2573 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType,
2574 NULL, &info->rgAltEntry[i], 0, NULL, pbEncoded, &len);
2575 if (ret)
2577 pbEncoded += len;
2578 dataLen -= len;
2585 __EXCEPT_PAGE_FAULT
2587 SetLastError(STATUS_ACCESS_VIOLATION);
2588 ret = FALSE;
2590 __ENDTRY
2591 return ret;
2594 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2595 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2596 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2598 BOOL ret;
2600 __TRY
2602 const CERT_AUTHORITY_KEY_ID2_INFO *info = pvStructInfo;
2603 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2604 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2605 DWORD cItem = 0, cSwapped = 0;
2607 if (info->KeyId.cbData)
2609 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2610 swapped[cSwapped].pvStructInfo = &info->KeyId;
2611 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2612 items[cItem].pvStructInfo = &swapped[cSwapped];
2613 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2614 cSwapped++;
2615 cItem++;
2617 if (info->AuthorityCertIssuer.cAltEntry)
2619 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2620 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2621 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2622 items[cItem].pvStructInfo = &swapped[cSwapped];
2623 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2624 cSwapped++;
2625 cItem++;
2627 if (info->AuthorityCertSerialNumber.cbData)
2629 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2630 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2631 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2632 items[cItem].pvStructInfo = &swapped[cSwapped];
2633 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2634 cSwapped++;
2635 cItem++;
2637 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2638 pEncodePara, pbEncoded, pcbEncoded);
2640 __EXCEPT_PAGE_FAULT
2642 SetLastError(STATUS_ACCESS_VIOLATION);
2643 ret = FALSE;
2645 __ENDTRY
2646 return ret;
2649 static BOOL CRYPT_AsnEncodeAccessDescription(
2650 const CERT_ACCESS_DESCRIPTION *descr, BYTE *pbEncoded, DWORD *pcbEncoded)
2652 struct AsnEncodeSequenceItem items[] = {
2653 { descr->pszAccessMethod, CRYPT_AsnEncodeOid, 0 },
2654 { &descr->AccessLocation, CRYPT_AsnEncodeAltNameEntry, 0 },
2657 if (!descr->pszAccessMethod)
2659 SetLastError(E_INVALIDARG);
2660 return FALSE;
2662 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
2663 sizeof(items) / sizeof(items[0]), 0, NULL, pbEncoded, pcbEncoded);
2666 static BOOL WINAPI CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType,
2667 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2668 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2670 BOOL ret;
2672 __TRY
2674 DWORD bytesNeeded, dataLen, lenBytes, i;
2675 const CERT_AUTHORITY_INFO_ACCESS *info = pvStructInfo;
2677 ret = TRUE;
2678 for (i = 0, dataLen = 0; ret && i < info->cAccDescr; i++)
2680 DWORD size;
2682 ret = CRYPT_AsnEncodeAccessDescription(&info->rgAccDescr[i], NULL,
2683 &size);
2684 if (ret)
2685 dataLen += size;
2687 if (ret)
2689 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2690 bytesNeeded = 1 + lenBytes + dataLen;
2691 if (!pbEncoded)
2692 *pcbEncoded = bytesNeeded;
2693 else
2695 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2696 pbEncoded, pcbEncoded, bytesNeeded)))
2698 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2699 pbEncoded = *(BYTE **)pbEncoded;
2700 *pbEncoded++ = ASN_SEQUENCEOF;
2701 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2702 pbEncoded += lenBytes;
2703 for (i = 0; i < info->cAccDescr; i++)
2705 DWORD size = dataLen;
2707 ret = CRYPT_AsnEncodeAccessDescription(
2708 &info->rgAccDescr[i], pbEncoded, &size);
2709 pbEncoded += size;
2710 dataLen -= size;
2716 __EXCEPT_PAGE_FAULT
2718 SetLastError(STATUS_ACCESS_VIOLATION);
2719 ret = FALSE;
2721 __ENDTRY
2722 return ret;
2725 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2726 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2727 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2729 BOOL ret;
2731 __TRY
2733 const CERT_BASIC_CONSTRAINTS_INFO *info = pvStructInfo;
2734 struct AsnEncodeSequenceItem items[3] = {
2735 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2736 { 0 }
2738 DWORD cItem = 1;
2740 if (info->fPathLenConstraint)
2742 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2743 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2744 cItem++;
2746 if (info->cSubtreesConstraint)
2748 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2749 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2750 cItem++;
2752 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2753 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2755 __EXCEPT_PAGE_FAULT
2757 SetLastError(STATUS_ACCESS_VIOLATION);
2758 ret = FALSE;
2760 __ENDTRY
2761 return ret;
2764 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2765 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2766 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2768 BOOL ret;
2770 __TRY
2772 const CERT_BASIC_CONSTRAINTS2_INFO *info = pvStructInfo;
2773 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2774 DWORD cItem = 0;
2776 if (info->fCA)
2778 items[cItem].pvStructInfo = &info->fCA;
2779 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2780 cItem++;
2782 if (info->fPathLenConstraint)
2784 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2785 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2786 cItem++;
2788 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2789 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2791 __EXCEPT_PAGE_FAULT
2793 SetLastError(STATUS_ACCESS_VIOLATION);
2794 ret = FALSE;
2796 __ENDTRY
2797 return ret;
2800 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType,
2801 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2802 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2804 DWORD cPolicyQualifier = *(DWORD *)pvStructInfo;
2805 const CERT_POLICY_QUALIFIER_INFO *rgPolicyQualifier =
2806 *(const CERT_POLICY_QUALIFIER_INFO **)
2807 ((LPBYTE)pvStructInfo + sizeof(DWORD));
2808 BOOL ret;
2810 if (!cPolicyQualifier)
2812 *pcbEncoded = 0;
2813 ret = TRUE;
2815 else
2817 struct AsnEncodeSequenceItem items[2] = {
2818 { NULL, CRYPT_AsnEncodeOid, 0 },
2819 { NULL, CRYPT_CopyEncodedBlob, 0 },
2821 DWORD bytesNeeded = 0, lenBytes, size, i;
2823 ret = TRUE;
2824 for (i = 0; ret && i < cPolicyQualifier; i++)
2826 items[0].pvStructInfo = rgPolicyQualifier[i].pszPolicyQualifierId;
2827 items[1].pvStructInfo = &rgPolicyQualifier[i].Qualifier;
2828 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2829 sizeof(items) / sizeof(items[0]),
2830 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
2831 if (ret)
2832 bytesNeeded += size;
2834 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2835 bytesNeeded += 1 + lenBytes;
2836 if (ret)
2838 if (!pbEncoded)
2839 *pcbEncoded = bytesNeeded;
2840 else
2842 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2843 pbEncoded, pcbEncoded, bytesNeeded)))
2845 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2846 pbEncoded = *(BYTE **)pbEncoded;
2847 *pbEncoded++ = ASN_SEQUENCEOF;
2848 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
2849 &lenBytes);
2850 pbEncoded += lenBytes;
2851 for (i = 0; ret && i < cPolicyQualifier; i++)
2853 items[0].pvStructInfo =
2854 rgPolicyQualifier[i].pszPolicyQualifierId;
2855 items[1].pvStructInfo =
2856 &rgPolicyQualifier[i].Qualifier;
2857 size = bytesNeeded;
2858 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2859 sizeof(items) / sizeof(items[0]),
2860 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
2861 &size);
2862 if (ret)
2864 pbEncoded += size;
2865 bytesNeeded -= size;
2872 return ret;
2875 static BOOL CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType,
2876 const CERT_POLICY_INFO *info, DWORD dwFlags, BYTE *pbEncoded,
2877 DWORD *pcbEncoded)
2879 struct AsnEncodeSequenceItem items[2] = {
2880 { info->pszPolicyIdentifier, CRYPT_AsnEncodeOid, 0 },
2881 { &info->cPolicyQualifier, CRYPT_AsnEncodeCertPolicyQualifiers, 0 },
2883 BOOL ret;
2885 if (!info->pszPolicyIdentifier)
2887 SetLastError(E_INVALIDARG);
2888 return FALSE;
2890 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2891 sizeof(items) / sizeof(items[0]), dwFlags, NULL, pbEncoded, pcbEncoded);
2892 return ret;
2895 static BOOL WINAPI CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType,
2896 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2897 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2899 BOOL ret = FALSE;
2901 __TRY
2903 const CERT_POLICIES_INFO *info = pvStructInfo;
2904 DWORD bytesNeeded = 0, lenBytes, size, i;
2906 ret = TRUE;
2907 for (i = 0; ret && i < info->cPolicyInfo; i++)
2909 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
2910 &info->rgPolicyInfo[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
2911 &size);
2912 if (ret)
2913 bytesNeeded += size;
2915 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2916 bytesNeeded += 1 + lenBytes;
2917 if (ret)
2919 if (!pbEncoded)
2920 *pcbEncoded = bytesNeeded;
2921 else
2923 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2924 pbEncoded, pcbEncoded, bytesNeeded)))
2926 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2927 pbEncoded = *(BYTE **)pbEncoded;
2928 *pbEncoded++ = ASN_SEQUENCEOF;
2929 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
2930 &lenBytes);
2931 pbEncoded += lenBytes;
2932 for (i = 0; ret && i < info->cPolicyInfo; i++)
2934 size = bytesNeeded;
2935 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
2936 &info->rgPolicyInfo[i],
2937 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pbEncoded, &size);
2938 if (ret)
2940 pbEncoded += size;
2941 bytesNeeded -= size;
2948 __EXCEPT_PAGE_FAULT
2950 SetLastError(STATUS_ACCESS_VIOLATION);
2952 __ENDTRY
2953 return ret;
2956 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
2957 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2958 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2960 BOOL ret;
2962 __TRY
2964 const BLOBHEADER *hdr = pvStructInfo;
2966 if (hdr->bType != PUBLICKEYBLOB)
2968 SetLastError(E_INVALIDARG);
2969 ret = FALSE;
2971 else
2973 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
2974 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
2975 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
2976 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
2977 struct AsnEncodeSequenceItem items[] = {
2978 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
2979 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
2982 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2983 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
2984 pcbEncoded);
2987 __EXCEPT_PAGE_FAULT
2989 SetLastError(STATUS_ACCESS_VIOLATION);
2990 ret = FALSE;
2992 __ENDTRY
2993 return ret;
2996 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
2997 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2998 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3000 BOOL ret;
3002 __TRY
3004 const CRYPT_DATA_BLOB *blob = pvStructInfo;
3005 DWORD bytesNeeded, lenBytes;
3007 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
3008 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
3010 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
3011 bytesNeeded = 1 + lenBytes + blob->cbData;
3012 if (!pbEncoded)
3014 *pcbEncoded = bytesNeeded;
3015 ret = TRUE;
3017 else
3019 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3020 pcbEncoded, bytesNeeded)))
3022 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3023 pbEncoded = *(BYTE **)pbEncoded;
3024 *pbEncoded++ = ASN_OCTETSTRING;
3025 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
3026 pbEncoded += lenBytes;
3027 if (blob->cbData)
3028 memcpy(pbEncoded, blob->pbData, blob->cbData);
3032 __EXCEPT_PAGE_FAULT
3034 SetLastError(STATUS_ACCESS_VIOLATION);
3035 ret = FALSE;
3037 __ENDTRY
3038 TRACE("returning %d (%08x)\n", ret, GetLastError());
3039 return ret;
3042 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
3043 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3044 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3046 BOOL ret;
3048 __TRY
3050 const CRYPT_BIT_BLOB *blob = pvStructInfo;
3051 DWORD bytesNeeded, lenBytes, dataBytes;
3052 BYTE unusedBits;
3054 /* yep, MS allows cUnusedBits to be >= 8 */
3055 if (!blob->cUnusedBits)
3057 dataBytes = blob->cbData;
3058 unusedBits = 0;
3060 else if (blob->cbData * 8 > blob->cUnusedBits)
3062 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
3063 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
3064 blob->cUnusedBits;
3066 else
3068 dataBytes = 0;
3069 unusedBits = 0;
3071 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
3072 bytesNeeded = 1 + lenBytes + dataBytes + 1;
3073 if (!pbEncoded)
3075 *pcbEncoded = bytesNeeded;
3076 ret = TRUE;
3078 else
3080 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3081 pcbEncoded, bytesNeeded)))
3083 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3084 pbEncoded = *(BYTE **)pbEncoded;
3085 *pbEncoded++ = ASN_BITSTRING;
3086 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
3087 pbEncoded += lenBytes;
3088 *pbEncoded++ = unusedBits;
3089 if (dataBytes)
3091 BYTE mask = 0xff << unusedBits;
3093 if (dataBytes > 1)
3095 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
3096 pbEncoded += dataBytes - 1;
3098 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
3103 __EXCEPT_PAGE_FAULT
3105 SetLastError(STATUS_ACCESS_VIOLATION);
3106 ret = FALSE;
3108 __ENDTRY
3109 return ret;
3112 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
3113 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3114 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3116 BOOL ret;
3118 __TRY
3120 const CRYPT_BIT_BLOB *blob = pvStructInfo;
3121 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
3123 ret = TRUE;
3124 if (newBlob.cbData)
3126 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
3127 if (newBlob.pbData)
3129 DWORD i;
3131 for (i = 0; i < newBlob.cbData; i++)
3132 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
3134 else
3135 ret = FALSE;
3137 if (ret)
3138 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
3139 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3140 CryptMemFree(newBlob.pbData);
3142 __EXCEPT_PAGE_FAULT
3144 SetLastError(STATUS_ACCESS_VIOLATION);
3145 ret = FALSE;
3147 __ENDTRY
3148 return ret;
3151 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
3152 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3153 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3155 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
3157 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
3158 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3161 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
3162 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3163 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3165 BOOL ret;
3167 __TRY
3169 DWORD significantBytes, lenBytes, bytesNeeded;
3170 BYTE padByte = 0;
3171 BOOL pad = FALSE;
3172 const CRYPT_INTEGER_BLOB *blob = pvStructInfo;
3174 significantBytes = blob->cbData;
3175 if (significantBytes)
3177 if (blob->pbData[significantBytes - 1] & 0x80)
3179 /* negative, lop off leading (little-endian) 0xffs */
3180 for (; significantBytes > 0 &&
3181 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
3183 if (blob->pbData[significantBytes - 1] < 0x80)
3185 padByte = 0xff;
3186 pad = TRUE;
3189 else
3191 /* positive, lop off leading (little-endian) zeroes */
3192 for (; significantBytes > 0 &&
3193 !blob->pbData[significantBytes - 1]; significantBytes--)
3195 if (significantBytes == 0)
3196 significantBytes = 1;
3197 if (blob->pbData[significantBytes - 1] > 0x7f)
3199 padByte = 0;
3200 pad = TRUE;
3204 if (pad)
3205 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3206 else
3207 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3208 bytesNeeded = 1 + lenBytes + significantBytes;
3209 if (pad)
3210 bytesNeeded++;
3211 if (!pbEncoded)
3213 *pcbEncoded = bytesNeeded;
3214 ret = TRUE;
3216 else
3218 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3219 pcbEncoded, bytesNeeded)))
3221 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3222 pbEncoded = *(BYTE **)pbEncoded;
3223 *pbEncoded++ = ASN_INTEGER;
3224 if (pad)
3226 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3227 pbEncoded += lenBytes;
3228 *pbEncoded++ = padByte;
3230 else
3232 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3233 pbEncoded += lenBytes;
3235 for (; significantBytes > 0; significantBytes--)
3236 *(pbEncoded++) = blob->pbData[significantBytes - 1];
3240 __EXCEPT_PAGE_FAULT
3242 SetLastError(STATUS_ACCESS_VIOLATION);
3243 ret = FALSE;
3245 __ENDTRY
3246 return ret;
3249 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
3250 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3251 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3253 BOOL ret;
3255 __TRY
3257 DWORD significantBytes, lenBytes, bytesNeeded;
3258 BOOL pad = FALSE;
3259 const CRYPT_INTEGER_BLOB *blob = pvStructInfo;
3261 significantBytes = blob->cbData;
3262 if (significantBytes)
3264 /* positive, lop off leading (little-endian) zeroes */
3265 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
3266 significantBytes--)
3268 if (significantBytes == 0)
3269 significantBytes = 1;
3270 if (blob->pbData[significantBytes - 1] > 0x7f)
3271 pad = TRUE;
3273 if (pad)
3274 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3275 else
3276 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3277 bytesNeeded = 1 + lenBytes + significantBytes;
3278 if (pad)
3279 bytesNeeded++;
3280 if (!pbEncoded)
3282 *pcbEncoded = bytesNeeded;
3283 ret = TRUE;
3285 else
3287 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3288 pcbEncoded, bytesNeeded)))
3290 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3291 pbEncoded = *(BYTE **)pbEncoded;
3292 *pbEncoded++ = ASN_INTEGER;
3293 if (pad)
3295 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3296 pbEncoded += lenBytes;
3297 *pbEncoded++ = 0;
3299 else
3301 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3302 pbEncoded += lenBytes;
3304 for (; significantBytes > 0; significantBytes--)
3305 *(pbEncoded++) = blob->pbData[significantBytes - 1];
3309 __EXCEPT_PAGE_FAULT
3311 SetLastError(STATUS_ACCESS_VIOLATION);
3312 ret = FALSE;
3314 __ENDTRY
3315 return ret;
3318 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
3319 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3320 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3322 CRYPT_INTEGER_BLOB blob;
3323 BOOL ret;
3325 /* Encode as an unsigned integer, then change the tag to enumerated */
3326 blob.cbData = sizeof(DWORD);
3327 blob.pbData = (BYTE *)pvStructInfo;
3328 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
3329 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3330 if (ret && pbEncoded)
3332 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3333 pbEncoded = *(BYTE **)pbEncoded;
3334 pbEncoded[0] = ASN_ENUMERATED;
3336 return ret;
3339 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
3340 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3341 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3343 BOOL ret;
3345 __TRY
3347 SYSTEMTIME sysTime;
3348 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
3349 * temporary buffer because the output buffer is not NULL-terminated.
3351 char buf[16];
3352 static const DWORD bytesNeeded = sizeof(buf) - 1;
3354 if (!pbEncoded)
3356 *pcbEncoded = bytesNeeded;
3357 ret = TRUE;
3359 else
3361 /* Sanity check the year, this is a two-digit year format */
3362 ret = FileTimeToSystemTime(pvStructInfo, &sysTime);
3363 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
3365 SetLastError(CRYPT_E_BAD_ENCODE);
3366 ret = FALSE;
3368 if (ret)
3370 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3371 pbEncoded, pcbEncoded, bytesNeeded)))
3373 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3374 pbEncoded = *(BYTE **)pbEncoded;
3375 buf[0] = ASN_UTCTIME;
3376 buf[1] = bytesNeeded - 2;
3377 snprintf(buf + 2, sizeof(buf) - 2,
3378 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
3379 sysTime.wYear - 2000 : sysTime.wYear - 1900,
3380 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3381 sysTime.wMinute, sysTime.wSecond);
3382 memcpy(pbEncoded, buf, bytesNeeded);
3387 __EXCEPT_PAGE_FAULT
3389 SetLastError(STATUS_ACCESS_VIOLATION);
3390 ret = FALSE;
3392 __ENDTRY
3393 return ret;
3396 static BOOL CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
3397 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3398 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3400 BOOL ret;
3402 __TRY
3404 SYSTEMTIME sysTime;
3405 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
3406 * temporary buffer because the output buffer is not NULL-terminated.
3408 char buf[18];
3409 static const DWORD bytesNeeded = sizeof(buf) - 1;
3411 if (!pbEncoded)
3413 *pcbEncoded = bytesNeeded;
3414 ret = TRUE;
3416 else
3418 ret = FileTimeToSystemTime(pvStructInfo, &sysTime);
3419 if (ret)
3420 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3421 pcbEncoded, bytesNeeded);
3422 if (ret)
3424 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3425 pbEncoded = *(BYTE **)pbEncoded;
3426 buf[0] = ASN_GENERALTIME;
3427 buf[1] = bytesNeeded - 2;
3428 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
3429 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3430 sysTime.wMinute, sysTime.wSecond);
3431 memcpy(pbEncoded, buf, bytesNeeded);
3435 __EXCEPT_PAGE_FAULT
3437 SetLastError(STATUS_ACCESS_VIOLATION);
3438 ret = FALSE;
3440 __ENDTRY
3441 return ret;
3444 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
3445 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3446 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3448 BOOL ret;
3450 __TRY
3452 SYSTEMTIME sysTime;
3454 /* Check the year, if it's in the UTCTime range call that encode func */
3455 if (!FileTimeToSystemTime(pvStructInfo, &sysTime))
3456 return FALSE;
3457 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
3458 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
3459 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3460 else
3461 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
3462 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
3463 pcbEncoded);
3465 __EXCEPT_PAGE_FAULT
3467 SetLastError(STATUS_ACCESS_VIOLATION);
3468 ret = FALSE;
3470 __ENDTRY
3471 return ret;
3474 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
3475 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3476 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3478 BOOL ret;
3480 __TRY
3482 DWORD bytesNeeded, dataLen, lenBytes, i;
3483 const CRYPT_SEQUENCE_OF_ANY *seq = pvStructInfo;
3485 for (i = 0, dataLen = 0; i < seq->cValue; i++)
3486 dataLen += seq->rgValue[i].cbData;
3487 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3488 bytesNeeded = 1 + lenBytes + dataLen;
3489 if (!pbEncoded)
3491 *pcbEncoded = bytesNeeded;
3492 ret = TRUE;
3494 else
3496 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3497 pcbEncoded, bytesNeeded)))
3499 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3500 pbEncoded = *(BYTE **)pbEncoded;
3501 *pbEncoded++ = ASN_SEQUENCEOF;
3502 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
3503 pbEncoded += lenBytes;
3504 for (i = 0; i < seq->cValue; i++)
3506 memcpy(pbEncoded, seq->rgValue[i].pbData,
3507 seq->rgValue[i].cbData);
3508 pbEncoded += seq->rgValue[i].cbData;
3513 __EXCEPT_PAGE_FAULT
3515 SetLastError(STATUS_ACCESS_VIOLATION);
3516 ret = FALSE;
3518 __ENDTRY
3519 return ret;
3522 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
3523 BYTE *pbEncoded, DWORD *pcbEncoded)
3525 BOOL ret = TRUE;
3526 struct AsnEncodeSequenceItem items[3] = { { 0 } };
3527 struct AsnConstructedItem constructed = { 0 };
3528 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
3529 DWORD cItem = 0, cSwapped = 0;
3531 switch (distPoint->DistPointName.dwDistPointNameChoice)
3533 case CRL_DIST_POINT_NO_NAME:
3534 /* do nothing */
3535 break;
3536 case CRL_DIST_POINT_FULL_NAME:
3537 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3538 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
3539 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3540 constructed.tag = 0;
3541 constructed.pvStructInfo = &swapped[cSwapped];
3542 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3543 items[cItem].pvStructInfo = &constructed;
3544 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3545 cSwapped++;
3546 cItem++;
3547 break;
3548 case CRL_DIST_POINT_ISSUER_RDN_NAME:
3549 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3550 ret = FALSE;
3551 break;
3552 default:
3553 ret = FALSE;
3555 if (ret && distPoint->ReasonFlags.cbData)
3557 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3558 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
3559 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3560 items[cItem].pvStructInfo = &swapped[cSwapped];
3561 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3562 cSwapped++;
3563 cItem++;
3565 if (ret && distPoint->CRLIssuer.cAltEntry)
3567 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
3568 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
3569 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3570 items[cItem].pvStructInfo = &swapped[cSwapped];
3571 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3572 cSwapped++;
3573 cItem++;
3575 if (ret)
3576 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
3577 pbEncoded, pcbEncoded);
3578 return ret;
3581 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
3582 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3583 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3585 BOOL ret;
3587 __TRY
3589 const CRL_DIST_POINTS_INFO *info = pvStructInfo;
3591 if (!info->cDistPoint)
3593 SetLastError(E_INVALIDARG);
3594 ret = FALSE;
3596 else
3598 DWORD bytesNeeded, dataLen, lenBytes, i;
3600 ret = TRUE;
3601 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
3603 DWORD len;
3605 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
3606 &len);
3607 if (ret)
3608 dataLen += len;
3609 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
3611 /* Have to propagate index of failing character */
3612 *pcbEncoded = len;
3615 if (ret)
3617 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3618 bytesNeeded = 1 + lenBytes + dataLen;
3619 if (!pbEncoded)
3621 *pcbEncoded = bytesNeeded;
3622 ret = TRUE;
3624 else
3626 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3627 pbEncoded, pcbEncoded, bytesNeeded)))
3629 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3630 pbEncoded = *(BYTE **)pbEncoded;
3631 *pbEncoded++ = ASN_SEQUENCEOF;
3632 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
3633 pbEncoded += lenBytes;
3634 for (i = 0; ret && i < info->cDistPoint; i++)
3636 DWORD len = dataLen;
3638 ret = CRYPT_AsnEncodeDistPoint(
3639 &info->rgDistPoint[i], pbEncoded, &len);
3640 if (ret)
3642 pbEncoded += len;
3643 dataLen -= len;
3651 __EXCEPT_PAGE_FAULT
3653 SetLastError(STATUS_ACCESS_VIOLATION);
3654 ret = FALSE;
3656 __ENDTRY
3657 return ret;
3660 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3661 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3662 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3664 BOOL ret;
3666 __TRY
3668 const CERT_ENHKEY_USAGE *usage = pvStructInfo;
3669 DWORD bytesNeeded = 0, lenBytes, size, i;
3671 ret = TRUE;
3672 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3674 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3675 usage->rgpszUsageIdentifier[i],
3676 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
3677 if (ret)
3678 bytesNeeded += size;
3680 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3681 bytesNeeded += 1 + lenBytes;
3682 if (ret)
3684 if (!pbEncoded)
3685 *pcbEncoded = bytesNeeded;
3686 else
3688 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3689 pbEncoded, pcbEncoded, bytesNeeded)))
3691 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3692 pbEncoded = *(BYTE **)pbEncoded;
3693 *pbEncoded++ = ASN_SEQUENCEOF;
3694 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
3695 &lenBytes);
3696 pbEncoded += lenBytes;
3697 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3699 size = bytesNeeded;
3700 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3701 usage->rgpszUsageIdentifier[i],
3702 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
3703 &size);
3704 if (ret)
3706 pbEncoded += size;
3707 bytesNeeded -= size;
3714 __EXCEPT_PAGE_FAULT
3716 SetLastError(STATUS_ACCESS_VIOLATION);
3717 ret = FALSE;
3719 __ENDTRY
3720 return ret;
3723 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(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_ISSUING_DIST_POINT *point = pvStructInfo;
3732 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3733 struct AsnConstructedItem constructed = { 0 };
3734 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3735 DWORD cItem = 0, cSwapped = 0;
3737 ret = TRUE;
3738 switch (point->DistPointName.dwDistPointNameChoice)
3740 case CRL_DIST_POINT_NO_NAME:
3741 /* do nothing */
3742 break;
3743 case CRL_DIST_POINT_FULL_NAME:
3744 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3745 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3746 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3747 constructed.tag = 0;
3748 constructed.pvStructInfo = &swapped[cSwapped];
3749 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3750 items[cItem].pvStructInfo = &constructed;
3751 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3752 cSwapped++;
3753 cItem++;
3754 break;
3755 default:
3756 SetLastError(E_INVALIDARG);
3757 ret = FALSE;
3759 if (ret && point->fOnlyContainsUserCerts)
3761 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3762 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3763 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3764 items[cItem].pvStructInfo = &swapped[cSwapped];
3765 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3766 cSwapped++;
3767 cItem++;
3769 if (ret && point->fOnlyContainsCACerts)
3771 swapped[cSwapped].tag = ASN_CONTEXT | 2;
3772 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3773 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3774 items[cItem].pvStructInfo = &swapped[cSwapped];
3775 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3776 cSwapped++;
3777 cItem++;
3779 if (ret && point->OnlySomeReasonFlags.cbData)
3781 swapped[cSwapped].tag = ASN_CONTEXT | 3;
3782 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3783 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3784 items[cItem].pvStructInfo = &swapped[cSwapped];
3785 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3786 cSwapped++;
3787 cItem++;
3789 if (ret && point->fIndirectCRL)
3791 swapped[cSwapped].tag = ASN_CONTEXT | 4;
3792 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
3793 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3794 items[cItem].pvStructInfo = &swapped[cSwapped];
3795 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3796 cSwapped++;
3797 cItem++;
3799 if (ret)
3800 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3801 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3803 __EXCEPT_PAGE_FAULT
3805 SetLastError(STATUS_ACCESS_VIOLATION);
3806 ret = FALSE;
3808 __ENDTRY
3809 return ret;
3812 static BOOL CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType,
3813 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3814 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3816 BOOL ret;
3817 const CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
3818 struct AsnEncodeSequenceItem items[3] = {
3819 { &subtree->Base, CRYPT_AsnEncodeAltNameEntry, 0 },
3820 { 0 }
3822 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3823 DWORD cItem = 1, cSwapped = 0;
3825 if (subtree->dwMinimum)
3827 swapped[cSwapped].tag = ASN_CONTEXT | 0;
3828 swapped[cSwapped].pvStructInfo = &subtree->dwMinimum;
3829 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3830 items[cItem].pvStructInfo = &swapped[cSwapped];
3831 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3832 cSwapped++;
3833 cItem++;
3835 if (subtree->fMaximum)
3837 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3838 swapped[cSwapped].pvStructInfo = &subtree->dwMaximum;
3839 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3840 items[cItem].pvStructInfo = &swapped[cSwapped];
3841 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3842 cSwapped++;
3843 cItem++;
3845 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags,
3846 pEncodePara, pbEncoded, pcbEncoded);
3847 return ret;
3850 static BOOL WINAPI CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType,
3851 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3852 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3854 BOOL ret = FALSE;
3855 CRYPT_BLOB_ARRAY permitted = { 0, NULL }, excluded = { 0, NULL };
3857 TRACE("%p\n", pvStructInfo);
3859 __TRY
3861 const CERT_NAME_CONSTRAINTS_INFO *constraints = pvStructInfo;
3862 struct AsnEncodeSequenceItem items[2] = { { 0 } };
3863 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3864 DWORD i, cItem = 0, cSwapped = 0;
3866 ret = TRUE;
3867 if (constraints->cPermittedSubtree)
3869 permitted.rgBlob = CryptMemAlloc(
3870 constraints->cPermittedSubtree * sizeof(CRYPT_DER_BLOB));
3871 if (permitted.rgBlob)
3873 permitted.cBlob = constraints->cPermittedSubtree;
3874 memset(permitted.rgBlob, 0,
3875 permitted.cBlob * sizeof(CRYPT_DER_BLOB));
3876 for (i = 0; ret && i < permitted.cBlob; i++)
3877 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3878 NULL, &constraints->rgPermittedSubtree[i],
3879 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3880 (BYTE *)&permitted.rgBlob[i].pbData,
3881 &permitted.rgBlob[i].cbData);
3882 if (ret)
3884 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3885 swapped[cSwapped].pvStructInfo = &permitted;
3886 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3887 items[cItem].pvStructInfo = &swapped[cSwapped];
3888 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3889 cSwapped++;
3890 cItem++;
3893 else
3894 ret = FALSE;
3896 if (constraints->cExcludedSubtree)
3898 excluded.rgBlob = CryptMemAlloc(
3899 constraints->cExcludedSubtree * sizeof(CRYPT_DER_BLOB));
3900 if (excluded.rgBlob)
3902 excluded.cBlob = constraints->cExcludedSubtree;
3903 memset(excluded.rgBlob, 0,
3904 excluded.cBlob * sizeof(CRYPT_DER_BLOB));
3905 for (i = 0; ret && i < excluded.cBlob; i++)
3906 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3907 NULL, &constraints->rgExcludedSubtree[i],
3908 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3909 (BYTE *)&excluded.rgBlob[i].pbData,
3910 &excluded.rgBlob[i].cbData);
3911 if (ret)
3913 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
3914 swapped[cSwapped].pvStructInfo = &excluded;
3915 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3916 items[cItem].pvStructInfo = &swapped[cSwapped];
3917 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3918 cSwapped++;
3919 cItem++;
3922 else
3923 ret = FALSE;
3925 if (ret)
3926 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3927 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3928 for (i = 0; i < permitted.cBlob; i++)
3929 LocalFree(permitted.rgBlob[i].pbData);
3930 for (i = 0; i < excluded.cBlob; i++)
3931 LocalFree(excluded.rgBlob[i].pbData);
3933 __EXCEPT_PAGE_FAULT
3935 SetLastError(STATUS_ACCESS_VIOLATION);
3937 __ENDTRY
3938 CryptMemFree(permitted.rgBlob);
3939 CryptMemFree(excluded.rgBlob);
3940 TRACE("returning %d\n", ret);
3941 return ret;
3944 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
3945 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3946 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3947 DWORD *pcbEncoded)
3949 BOOL ret;
3950 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
3951 struct AsnEncodeSequenceItem items[] = {
3952 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
3953 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
3956 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3957 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3958 pcbEncoded);
3959 return ret;
3962 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
3963 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3964 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3966 BOOL ret = FALSE;
3968 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
3970 SetLastError(E_INVALIDARG);
3971 return FALSE;
3974 __TRY
3976 const CMSG_SIGNER_INFO *info = pvStructInfo;
3978 if (!info->Issuer.cbData)
3979 SetLastError(E_INVALIDARG);
3980 else
3982 struct AsnEncodeSequenceItem items[7] = {
3983 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
3984 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
3985 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
3986 0 },
3988 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3989 DWORD cItem = 3, cSwapped = 0;
3991 if (info->AuthAttrs.cAttr)
3993 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3994 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
3995 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3996 items[cItem].pvStructInfo = &swapped[cSwapped];
3997 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3998 cSwapped++;
3999 cItem++;
4001 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
4002 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4003 cItem++;
4004 items[cItem].pvStructInfo = &info->EncryptedHash;
4005 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
4006 cItem++;
4007 if (info->UnauthAttrs.cAttr)
4009 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4010 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
4011 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4012 items[cItem].pvStructInfo = &swapped[cSwapped];
4013 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4014 cSwapped++;
4015 cItem++;
4017 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4018 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4021 __EXCEPT_PAGE_FAULT
4023 SetLastError(STATUS_ACCESS_VIOLATION);
4025 __ENDTRY
4026 return ret;
4029 static BOOL WINAPI CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType,
4030 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4031 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4033 BOOL ret = FALSE;
4035 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
4037 SetLastError(E_INVALIDARG);
4038 return FALSE;
4041 __TRY
4043 const CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
4045 if (info->SignerId.dwIdChoice != CERT_ID_ISSUER_SERIAL_NUMBER &&
4046 info->SignerId.dwIdChoice != CERT_ID_KEY_IDENTIFIER)
4047 SetLastError(E_INVALIDARG);
4048 else if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER &&
4049 !info->SignerId.u.IssuerSerialNumber.Issuer.cbData)
4050 SetLastError(E_INVALIDARG);
4051 else
4053 struct AsnEncodeSequenceItem items[7] = {
4054 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4056 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
4057 DWORD cItem = 1, cSwapped = 0;
4059 if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
4061 items[cItem].pvStructInfo =
4062 &info->SignerId.u.IssuerSerialNumber.Issuer;
4063 items[cItem].encodeFunc =
4064 CRYPT_AsnEncodeIssuerSerialNumber;
4065 cItem++;
4067 else
4069 swapped[cSwapped].tag = ASN_CONTEXT | 0;
4070 swapped[cSwapped].pvStructInfo = &info->SignerId.u.KeyId;
4071 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
4072 items[cItem].pvStructInfo = &swapped[cSwapped];
4073 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4074 cSwapped++;
4075 cItem++;
4077 items[cItem].pvStructInfo = &info->HashAlgorithm;
4078 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4079 cItem++;
4080 if (info->AuthAttrs.cAttr)
4082 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4083 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
4084 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4085 items[cItem].pvStructInfo = &swapped[cSwapped];
4086 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4087 cSwapped++;
4088 cItem++;
4090 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
4091 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4092 cItem++;
4093 items[cItem].pvStructInfo = &info->EncryptedHash;
4094 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
4095 cItem++;
4096 if (info->UnauthAttrs.cAttr)
4098 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4099 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
4100 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4101 items[cItem].pvStructInfo = &swapped[cSwapped];
4102 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4103 cSwapped++;
4104 cItem++;
4106 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4107 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4110 __EXCEPT_PAGE_FAULT
4112 SetLastError(STATUS_ACCESS_VIOLATION);
4114 __ENDTRY
4115 return ret;
4118 BOOL CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
4119 DWORD *pcbData)
4121 struct AsnEncodeSequenceItem items[7] = {
4122 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
4124 struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 };
4125 struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 };
4126 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4127 DWORD cItem = 1, cSwapped = 0;
4128 BOOL ret = TRUE;
4130 if (signedInfo->cSignerInfo)
4132 digestAlgorithmsSet.cItems = signedInfo->cSignerInfo;
4133 digestAlgorithmsSet.items = signedInfo->rgSignerInfo;
4134 digestAlgorithmsSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
4135 digestAlgorithmsSet.itemOffset =
4136 offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm);
4137 digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4138 items[cItem].pvStructInfo = &digestAlgorithmsSet;
4139 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4140 cItem++;
4142 items[cItem].pvStructInfo = &signedInfo->content;
4143 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal;
4144 cItem++;
4145 if (signedInfo->cCertEncoded)
4147 certSet.cItems = signedInfo->cCertEncoded;
4148 certSet.items = signedInfo->rgCertEncoded;
4149 certSet.itemSize = sizeof(CERT_BLOB);
4150 certSet.itemOffset = 0;
4151 certSet.encode = CRYPT_CopyEncodedBlob;
4152 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0;
4153 swapped[cSwapped].pvStructInfo = &certSet;
4154 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4155 items[cItem].pvStructInfo = &swapped[cSwapped];
4156 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4157 cSwapped++;
4158 cItem++;
4160 if (signedInfo->cCrlEncoded)
4162 crlSet.cItems = signedInfo->cCrlEncoded;
4163 crlSet.items = signedInfo->rgCrlEncoded;
4164 crlSet.itemSize = sizeof(CRL_BLOB);
4165 crlSet.itemOffset = 0;
4166 crlSet.encode = CRYPT_CopyEncodedBlob;
4167 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
4168 swapped[cSwapped].pvStructInfo = &crlSet;
4169 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4170 items[cItem].pvStructInfo = &swapped[cSwapped];
4171 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4172 cSwapped++;
4173 cItem++;
4175 if (ret && signedInfo->cSignerInfo)
4177 signerSet.cItems = signedInfo->cSignerInfo;
4178 signerSet.items = signedInfo->rgSignerInfo;
4179 signerSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
4180 signerSet.itemOffset = 0;
4181 signerSet.encode = CRYPT_AsnEncodeCMSSignerInfo;
4182 items[cItem].pvStructInfo = &signerSet;
4183 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4184 cItem++;
4186 if (ret)
4187 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
4188 items, cItem, 0, NULL, pvData, pcbData);
4190 return ret;
4193 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
4194 LPCSTR lpszStructType)
4196 CryptEncodeObjectExFunc encodeFunc = NULL;
4198 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4199 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4201 SetLastError(ERROR_FILE_NOT_FOUND);
4202 return NULL;
4205 if (!HIWORD(lpszStructType))
4207 switch (LOWORD(lpszStructType))
4209 case LOWORD(X509_CERT):
4210 encodeFunc = CRYPT_AsnEncodeCert;
4211 break;
4212 case LOWORD(X509_CERT_TO_BE_SIGNED):
4213 encodeFunc = CRYPT_AsnEncodeCertInfo;
4214 break;
4215 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
4216 encodeFunc = CRYPT_AsnEncodeCRLInfo;
4217 break;
4218 case LOWORD(X509_EXTENSIONS):
4219 encodeFunc = CRYPT_AsnEncodeExtensions;
4220 break;
4221 case LOWORD(X509_NAME_VALUE):
4222 encodeFunc = CRYPT_AsnEncodeNameValue;
4223 break;
4224 case LOWORD(X509_NAME):
4225 encodeFunc = CRYPT_AsnEncodeName;
4226 break;
4227 case LOWORD(X509_PUBLIC_KEY_INFO):
4228 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
4229 break;
4230 case LOWORD(X509_AUTHORITY_KEY_ID):
4231 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
4232 break;
4233 case LOWORD(X509_ALTERNATE_NAME):
4234 encodeFunc = CRYPT_AsnEncodeAltName;
4235 break;
4236 case LOWORD(X509_BASIC_CONSTRAINTS):
4237 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
4238 break;
4239 case LOWORD(X509_BASIC_CONSTRAINTS2):
4240 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
4241 break;
4242 case LOWORD(X509_CERT_POLICIES):
4243 encodeFunc = CRYPT_AsnEncodeCertPolicies;
4244 break;
4245 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
4246 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
4247 break;
4248 case LOWORD(X509_UNICODE_NAME):
4249 encodeFunc = CRYPT_AsnEncodeUnicodeName;
4250 break;
4251 case LOWORD(PKCS_CONTENT_INFO):
4252 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
4253 break;
4254 case LOWORD(PKCS_ATTRIBUTE):
4255 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
4256 break;
4257 case LOWORD(X509_UNICODE_NAME_VALUE):
4258 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
4259 break;
4260 case LOWORD(X509_OCTET_STRING):
4261 encodeFunc = CRYPT_AsnEncodeOctets;
4262 break;
4263 case LOWORD(X509_BITS):
4264 case LOWORD(X509_KEY_USAGE):
4265 encodeFunc = CRYPT_AsnEncodeBits;
4266 break;
4267 case LOWORD(X509_INTEGER):
4268 encodeFunc = CRYPT_AsnEncodeInt;
4269 break;
4270 case LOWORD(X509_MULTI_BYTE_INTEGER):
4271 encodeFunc = CRYPT_AsnEncodeInteger;
4272 break;
4273 case LOWORD(X509_MULTI_BYTE_UINT):
4274 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
4275 break;
4276 case LOWORD(X509_ENUMERATED):
4277 encodeFunc = CRYPT_AsnEncodeEnumerated;
4278 break;
4279 case LOWORD(X509_CHOICE_OF_TIME):
4280 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
4281 break;
4282 case LOWORD(X509_AUTHORITY_KEY_ID2):
4283 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
4284 break;
4285 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
4286 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
4287 break;
4288 case LOWORD(X509_SEQUENCE_OF_ANY):
4289 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
4290 break;
4291 case LOWORD(PKCS_UTC_TIME):
4292 encodeFunc = CRYPT_AsnEncodeUtcTime;
4293 break;
4294 case LOWORD(X509_CRL_DIST_POINTS):
4295 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
4296 break;
4297 case LOWORD(X509_ENHANCED_KEY_USAGE):
4298 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
4299 break;
4300 case LOWORD(PKCS_CTL):
4301 encodeFunc = CRYPT_AsnEncodeCTL;
4302 break;
4303 case LOWORD(PKCS_SMIME_CAPABILITIES):
4304 encodeFunc = CRYPT_AsnEncodeSMIMECapabilities;
4305 break;
4306 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
4307 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
4308 break;
4309 case LOWORD(PKCS_ATTRIBUTES):
4310 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4311 break;
4312 case LOWORD(X509_ISSUING_DIST_POINT):
4313 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
4314 break;
4315 case LOWORD(X509_NAME_CONSTRAINTS):
4316 encodeFunc = CRYPT_AsnEncodeNameConstraints;
4317 break;
4318 case LOWORD(PKCS7_SIGNER_INFO):
4319 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
4320 break;
4321 case LOWORD(CMS_SIGNER_INFO):
4322 encodeFunc = CRYPT_AsnEncodeCMSSignerInfo;
4323 break;
4326 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4327 encodeFunc = CRYPT_AsnEncodeExtensions;
4328 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4329 encodeFunc = CRYPT_AsnEncodeUtcTime;
4330 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
4331 encodeFunc = CRYPT_AsnEncodeUtcTime;
4332 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4333 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
4334 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4335 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
4336 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4337 encodeFunc = CRYPT_AsnEncodeEnumerated;
4338 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4339 encodeFunc = CRYPT_AsnEncodeBits;
4340 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4341 encodeFunc = CRYPT_AsnEncodeOctets;
4342 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4343 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
4344 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4345 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
4346 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4347 encodeFunc = CRYPT_AsnEncodeAltName;
4348 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4349 encodeFunc = CRYPT_AsnEncodeAltName;
4350 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4351 encodeFunc = CRYPT_AsnEncodeAltName;
4352 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4353 encodeFunc = CRYPT_AsnEncodeAltName;
4354 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4355 encodeFunc = CRYPT_AsnEncodeAltName;
4356 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4357 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
4358 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
4359 encodeFunc = CRYPT_AsnEncodeCertPolicies;
4360 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4361 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
4362 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4363 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
4364 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
4365 encodeFunc = CRYPT_AsnEncodeNameConstraints;
4366 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
4367 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
4368 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
4369 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
4370 else if (!strcmp(lpszStructType, szOID_CTL))
4371 encodeFunc = CRYPT_AsnEncodeCTL;
4372 return encodeFunc;
4375 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType,
4376 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4378 static HCRYPTOIDFUNCSET set = NULL;
4379 CryptEncodeObjectFunc encodeFunc = NULL;
4381 if (!set)
4382 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
4383 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4384 (void **)&encodeFunc, hFunc);
4385 return encodeFunc;
4388 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType,
4389 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4391 static HCRYPTOIDFUNCSET set = NULL;
4392 CryptEncodeObjectExFunc encodeFunc = NULL;
4394 if (!set)
4395 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
4396 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4397 (void **)&encodeFunc, hFunc);
4398 return encodeFunc;
4401 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4402 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
4404 BOOL ret = FALSE;
4405 HCRYPTOIDFUNCADDR hFunc = NULL;
4406 CryptEncodeObjectFunc pCryptEncodeObject = NULL;
4407 CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL;
4409 TRACE_(crypt)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
4410 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
4411 pcbEncoded);
4413 if (!pbEncoded && !pcbEncoded)
4415 SetLastError(ERROR_INVALID_PARAMETER);
4416 return FALSE;
4419 if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType,
4420 lpszStructType)))
4422 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4423 debugstr_a(lpszStructType));
4424 pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType,
4425 lpszStructType, &hFunc);
4426 if (!pCryptEncodeObject)
4427 pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType,
4428 lpszStructType, &hFunc);
4430 if (pCryptEncodeObject)
4431 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4432 pvStructInfo, pbEncoded, pcbEncoded);
4433 else if (pCryptEncodeObjectEx)
4434 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
4435 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
4436 if (hFunc)
4437 CryptFreeOIDFunctionAddress(hFunc, 0);
4438 TRACE_(crypt)("returning %d\n", ret);
4439 return ret;
4442 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4443 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
4444 void *pvEncoded, DWORD *pcbEncoded)
4446 BOOL ret = FALSE;
4447 HCRYPTOIDFUNCADDR hFunc = NULL;
4448 CryptEncodeObjectExFunc encodeFunc = NULL;
4450 TRACE_(crypt)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
4451 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
4452 pvEncoded, pcbEncoded);
4454 if (!pvEncoded && !pcbEncoded)
4456 SetLastError(ERROR_INVALID_PARAMETER);
4457 return FALSE;
4460 SetLastError(NOERROR);
4461 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
4462 *(BYTE **)pvEncoded = NULL;
4463 encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType);
4464 if (!encodeFunc)
4466 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4467 debugstr_a(lpszStructType));
4468 encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType,
4469 &hFunc);
4471 if (encodeFunc)
4472 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
4473 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
4474 else
4476 CryptEncodeObjectFunc pCryptEncodeObject =
4477 CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4479 if (pCryptEncodeObject)
4481 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
4483 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4484 pvStructInfo, NULL, pcbEncoded);
4485 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
4486 pvEncoded, pcbEncoded, *pcbEncoded)))
4487 ret = pCryptEncodeObject(dwCertEncodingType,
4488 lpszStructType, pvStructInfo, *(BYTE **)pvEncoded,
4489 pcbEncoded);
4491 else
4492 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4493 pvStructInfo, pvEncoded, pcbEncoded);
4496 if (hFunc)
4497 CryptFreeOIDFunctionAddress(hFunc, 0);
4498 TRACE_(crypt)("returning %d\n", ret);
4499 return ret;
4502 BOOL WINAPI PFXExportCertStore(HCERTSTORE hStore, CRYPT_DATA_BLOB *pPFX,
4503 LPCWSTR szPassword, DWORD dwFlags)
4505 return PFXExportCertStoreEx(hStore, pPFX, szPassword, NULL, dwFlags);
4508 BOOL WINAPI PFXExportCertStoreEx(HCERTSTORE hStore, CRYPT_DATA_BLOB *pPFX,
4509 LPCWSTR szPassword, void *pvReserved, DWORD dwFlags)
4511 FIXME_(crypt)("(%p, %p, %p, %p, %08x): stub\n", hStore, pPFX, szPassword,
4512 pvReserved, dwFlags);
4513 return FALSE;
4516 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
4517 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4519 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
4520 NULL, 0, NULL, pInfo, pcbInfo);
4523 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
4524 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
4525 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4527 BOOL ret;
4528 HCRYPTKEY key;
4529 static CHAR oid[] = szOID_RSA_RSA;
4531 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
4532 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
4533 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
4535 if (!pszPublicKeyObjId)
4536 pszPublicKeyObjId = oid;
4537 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
4539 DWORD keySize = 0;
4541 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
4542 if (ret)
4544 LPBYTE pubKey = CryptMemAlloc(keySize);
4546 if (pubKey)
4548 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
4549 &keySize);
4550 if (ret)
4552 DWORD encodedLen = 0;
4554 ret = CryptEncodeObject(dwCertEncodingType,
4555 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
4556 if (ret)
4558 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
4559 strlen(pszPublicKeyObjId) + 1 + encodedLen;
4561 if (!pInfo)
4562 *pcbInfo = sizeNeeded;
4563 else if (*pcbInfo < sizeNeeded)
4565 SetLastError(ERROR_MORE_DATA);
4566 *pcbInfo = sizeNeeded;
4567 ret = FALSE;
4569 else
4571 pInfo->Algorithm.pszObjId = (char *)pInfo +
4572 sizeof(CERT_PUBLIC_KEY_INFO);
4573 lstrcpyA(pInfo->Algorithm.pszObjId,
4574 pszPublicKeyObjId);
4575 pInfo->Algorithm.Parameters.cbData = 0;
4576 pInfo->Algorithm.Parameters.pbData = NULL;
4577 pInfo->PublicKey.pbData =
4578 (BYTE *)pInfo->Algorithm.pszObjId
4579 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
4580 pInfo->PublicKey.cbData = encodedLen;
4581 pInfo->PublicKey.cUnusedBits = 0;
4582 ret = CryptEncodeObject(dwCertEncodingType,
4583 RSA_CSP_PUBLICKEYBLOB, pubKey,
4584 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
4588 CryptMemFree(pubKey);
4590 else
4591 ret = FALSE;
4593 CryptDestroyKey(key);
4595 return ret;
4598 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
4599 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
4600 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
4602 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
4603 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
4604 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4606 static HCRYPTOIDFUNCSET set = NULL;
4607 BOOL ret;
4608 ExportPublicKeyInfoExFunc exportFunc = NULL;
4609 HCRYPTOIDFUNCADDR hFunc = NULL;
4611 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
4612 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
4613 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
4615 if (!hCryptProv)
4617 SetLastError(ERROR_INVALID_PARAMETER);
4618 return FALSE;
4621 if (pszPublicKeyObjId)
4623 if (!set)
4624 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
4626 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
4627 0, (void **)&exportFunc, &hFunc);
4629 if (!exportFunc)
4630 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
4631 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
4632 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
4633 if (hFunc)
4634 CryptFreeOIDFunctionAddress(hFunc, 0);
4635 return ret;
4638 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
4639 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
4641 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
4642 0, 0, NULL, phKey);
4645 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
4646 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4647 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
4649 BOOL ret;
4650 DWORD pubKeySize = 0;
4652 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
4653 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
4655 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
4656 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
4657 if (ret)
4659 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
4661 if (pubKey)
4663 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
4664 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
4665 &pubKeySize);
4666 if (ret)
4668 if(aiKeyAlg)
4669 ((BLOBHEADER*)pubKey)->aiKeyAlg = aiKeyAlg;
4670 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
4671 phKey);
4673 CryptMemFree(pubKey);
4675 else
4676 ret = FALSE;
4678 return ret;
4681 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
4682 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4683 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
4685 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
4686 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4687 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
4689 static HCRYPTOIDFUNCSET set = NULL;
4690 BOOL ret;
4691 ImportPublicKeyInfoExFunc importFunc = NULL;
4692 HCRYPTOIDFUNCADDR hFunc = NULL;
4694 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
4695 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
4697 if (!set)
4698 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
4699 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
4700 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
4701 if (!importFunc)
4702 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
4703 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
4704 pvAuxInfo, phKey);
4705 if (hFunc)
4706 CryptFreeOIDFunctionAddress(hFunc, 0);
4707 return ret;