push 9e645869891abdc47a8701768b7a401b196a1e38
[wine/hacks.git] / dlls / crypt32 / encode.c
blob9e102987721ebd556afaceae5f791c14937c1c78
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 =
232 (const struct AsnConstructedItem *)pvStructInfo;
233 DWORD len;
235 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
236 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
238 DWORD dataLen, bytesNeeded;
240 CRYPT_EncodeLen(len, NULL, &dataLen);
241 bytesNeeded = 1 + dataLen + len;
242 if (!pbEncoded)
243 *pcbEncoded = bytesNeeded;
244 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
245 pbEncoded, pcbEncoded, bytesNeeded)))
247 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
248 pbEncoded = *(BYTE **)pbEncoded;
249 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
250 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
251 pbEncoded += dataLen;
252 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
253 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
254 pbEncoded, &len);
255 if (!ret)
257 /* Some functions propagate their errors through the size */
258 *pcbEncoded = len;
262 else
264 /* Some functions propagate their errors through the size */
265 *pcbEncoded = len;
267 return ret;
270 struct AsnEncodeTagSwappedItem
272 BYTE tag;
273 const void *pvStructInfo;
274 CryptEncodeObjectExFunc encodeFunc;
277 /* Sort of a wacky hack, it encodes something using the struct
278 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
279 * given in the struct AsnEncodeTagSwappedItem.
281 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
282 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
283 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
285 BOOL ret;
286 const struct AsnEncodeTagSwappedItem *item =
287 (const struct AsnEncodeTagSwappedItem *)pvStructInfo;
289 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
290 item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
291 if (ret && pbEncoded)
292 *pbEncoded = item->tag;
293 return ret;
296 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
297 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
298 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
300 const DWORD *ver = (const DWORD *)pvStructInfo;
301 BOOL ret;
303 /* CERT_V1 is not encoded */
304 if (*ver == CERT_V1)
306 *pcbEncoded = 0;
307 ret = TRUE;
309 else
311 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
313 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
314 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
316 return ret;
319 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
320 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
321 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
323 const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
324 BOOL ret;
326 if (!pbEncoded)
328 *pcbEncoded = blob->cbData;
329 ret = TRUE;
331 else
333 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
334 pcbEncoded, blob->cbData)))
336 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
337 pbEncoded = *(BYTE **)pbEncoded;
338 if (blob->cbData)
339 memcpy(pbEncoded, blob->pbData, blob->cbData);
340 *pcbEncoded = blob->cbData;
341 ret = TRUE;
344 return ret;
347 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
348 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
349 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
351 BOOL ret;
352 /* This has two filetimes in a row, a NotBefore and a NotAfter */
353 const FILETIME *timePtr = (const FILETIME *)pvStructInfo;
354 struct AsnEncodeSequenceItem items[] = {
355 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
356 { timePtr + 1, CRYPT_AsnEncodeChoiceOfTime, 0 },
359 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
360 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
361 pcbEncoded);
362 return ret;
365 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
366 * if they are empty.
368 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
369 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
370 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
371 DWORD *pcbEncoded)
373 const CRYPT_ALGORITHM_IDENTIFIER *algo =
374 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
375 static const BYTE asn1Null[] = { ASN_NULL, 0 };
376 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
377 (LPBYTE)asn1Null };
378 BOOL ret;
379 struct AsnEncodeSequenceItem items[2] = {
380 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
381 { NULL, CRYPT_CopyEncodedBlob, 0 },
384 if (algo->Parameters.cbData)
385 items[1].pvStructInfo = &algo->Parameters;
386 else
387 items[1].pvStructInfo = &nullBlob;
388 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
389 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
390 pcbEncoded);
391 return ret;
394 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType,
395 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
396 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
398 const CRYPT_ALGORITHM_IDENTIFIER *algo =
399 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
400 BOOL ret;
401 struct AsnEncodeSequenceItem items[] = {
402 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
403 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
406 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
407 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
408 pcbEncoded);
409 return ret;
412 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
413 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
414 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
416 BOOL ret;
418 __TRY
420 const CERT_PUBLIC_KEY_INFO *info =
421 (const CERT_PUBLIC_KEY_INFO *)pvStructInfo;
422 struct AsnEncodeSequenceItem items[] = {
423 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
424 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
427 TRACE("Encoding public key with OID %s\n",
428 debugstr_a(info->Algorithm.pszObjId));
429 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
430 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
431 pcbEncoded);
433 __EXCEPT_PAGE_FAULT
435 SetLastError(STATUS_ACCESS_VIOLATION);
436 ret = FALSE;
438 __ENDTRY
439 return ret;
442 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
443 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
444 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
446 BOOL ret;
448 __TRY
450 const CERT_SIGNED_CONTENT_INFO *info =
451 (const CERT_SIGNED_CONTENT_INFO *)pvStructInfo;
452 struct AsnEncodeSequenceItem items[] = {
453 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
454 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
455 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
458 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
459 items[2].encodeFunc = CRYPT_AsnEncodeBits;
460 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
461 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
462 pcbEncoded);
464 __EXCEPT_PAGE_FAULT
466 SetLastError(STATUS_ACCESS_VIOLATION);
467 ret = FALSE;
469 __ENDTRY
470 return ret;
473 /* Like in Windows, this blithely ignores the validity of the passed-in
474 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
475 * decode properly, see CRYPT_AsnDecodeCertInfo.
477 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
478 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
479 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
481 BOOL ret;
483 __TRY
485 const CERT_INFO *info = (const CERT_INFO *)pvStructInfo;
486 struct AsnEncodeSequenceItem items[10] = {
487 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
488 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
489 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
490 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
491 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
492 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
493 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfo, 0 },
494 { 0 }
496 struct AsnConstructedItem constructed[3] = { { 0 } };
497 DWORD cItem = 7, cConstructed = 0;
499 if (info->IssuerUniqueId.cbData)
501 constructed[cConstructed].tag = 1;
502 constructed[cConstructed].pvStructInfo = &info->IssuerUniqueId;
503 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
504 items[cItem].pvStructInfo = &constructed[cConstructed];
505 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
506 cConstructed++;
507 cItem++;
509 if (info->SubjectUniqueId.cbData)
511 constructed[cConstructed].tag = 2;
512 constructed[cConstructed].pvStructInfo = &info->SubjectUniqueId;
513 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
514 items[cItem].pvStructInfo = &constructed[cConstructed];
515 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
516 cConstructed++;
517 cItem++;
519 if (info->cExtension)
521 constructed[cConstructed].tag = 3;
522 constructed[cConstructed].pvStructInfo = &info->cExtension;
523 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
524 items[cItem].pvStructInfo = &constructed[cConstructed];
525 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
526 cConstructed++;
527 cItem++;
530 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
531 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
533 __EXCEPT_PAGE_FAULT
535 SetLastError(STATUS_ACCESS_VIOLATION);
536 ret = FALSE;
538 __ENDTRY
539 return ret;
542 static BOOL WINAPI CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
543 BYTE *pbEncoded, DWORD *pcbEncoded)
545 struct AsnEncodeSequenceItem items[3] = {
546 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
547 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
548 { 0 }
550 DWORD cItem = 2;
551 BOOL ret;
553 TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded);
555 if (entry->cExtension)
557 items[cItem].pvStructInfo = &entry->cExtension;
558 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
559 cItem++;
562 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
563 pbEncoded, pcbEncoded);
565 TRACE("returning %d (%08x)\n", ret, GetLastError());
566 return ret;
569 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
570 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
571 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
573 DWORD cCRLEntry = *(const DWORD *)pvStructInfo;
574 DWORD bytesNeeded, dataLen, lenBytes, i;
575 const CRL_ENTRY *rgCRLEntry = *(const CRL_ENTRY *const *)
576 ((const BYTE *)pvStructInfo + sizeof(DWORD));
577 BOOL ret = TRUE;
579 for (i = 0, dataLen = 0; ret && i < cCRLEntry; i++)
581 DWORD size;
583 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
584 if (ret)
585 dataLen += size;
587 if (ret)
589 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
590 bytesNeeded = 1 + lenBytes + dataLen;
591 if (!pbEncoded)
592 *pcbEncoded = bytesNeeded;
593 else
595 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
596 pcbEncoded, bytesNeeded)))
598 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
599 pbEncoded = *(BYTE **)pbEncoded;
600 *pbEncoded++ = ASN_SEQUENCEOF;
601 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
602 pbEncoded += lenBytes;
603 for (i = 0; i < cCRLEntry; i++)
605 DWORD size = dataLen;
607 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], pbEncoded,
608 &size);
609 pbEncoded += size;
610 dataLen -= size;
615 return ret;
618 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
619 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
620 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
622 const DWORD *ver = (const DWORD *)pvStructInfo;
623 BOOL ret;
625 /* CRL_V1 is not encoded */
626 if (*ver == CRL_V1)
628 *pcbEncoded = 0;
629 ret = TRUE;
631 else
632 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
633 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
634 return ret;
637 /* Like in Windows, this blithely ignores the validity of the passed-in
638 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
639 * decode properly, see CRYPT_AsnDecodeCRLInfo.
641 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
642 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
643 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
645 BOOL ret;
647 __TRY
649 const CRL_INFO *info = (const CRL_INFO *)pvStructInfo;
650 struct AsnEncodeSequenceItem items[7] = {
651 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
652 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
653 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
654 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
655 { 0 }
657 struct AsnConstructedItem constructed[1] = { { 0 } };
658 DWORD cItem = 4, cConstructed = 0;
660 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
662 items[cItem].pvStructInfo = &info->NextUpdate;
663 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
664 cItem++;
666 if (info->cCRLEntry)
668 items[cItem].pvStructInfo = &info->cCRLEntry;
669 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
670 cItem++;
672 if (info->cExtension)
674 constructed[cConstructed].tag = 0;
675 constructed[cConstructed].pvStructInfo = &info->cExtension;
676 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
677 items[cItem].pvStructInfo = &constructed[cConstructed];
678 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
679 cConstructed++;
680 cItem++;
683 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
684 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
686 __EXCEPT_PAGE_FAULT
688 SetLastError(STATUS_ACCESS_VIOLATION);
689 ret = FALSE;
691 __ENDTRY
692 return ret;
695 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
696 DWORD *pcbEncoded)
698 BOOL ret;
699 struct AsnEncodeSequenceItem items[3] = {
700 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
701 { NULL, NULL, 0 },
702 { NULL, NULL, 0 },
704 DWORD cItem = 1;
706 TRACE("%p, %p, %d\n", ext, pbEncoded, *pcbEncoded);
708 if (ext->fCritical)
710 items[cItem].pvStructInfo = &ext->fCritical;
711 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
712 cItem++;
714 items[cItem].pvStructInfo = &ext->Value;
715 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
716 cItem++;
718 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
719 pbEncoded, pcbEncoded);
720 TRACE("returning %d (%08x)\n", ret, GetLastError());
721 return ret;
724 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
725 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
726 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
728 BOOL ret;
730 __TRY
732 DWORD bytesNeeded, dataLen, lenBytes, i;
733 const CERT_EXTENSIONS *exts = (const CERT_EXTENSIONS *)pvStructInfo;
735 ret = TRUE;
736 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
738 DWORD size;
740 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
741 if (ret)
742 dataLen += size;
744 if (ret)
746 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
747 bytesNeeded = 1 + lenBytes + dataLen;
748 if (!pbEncoded)
749 *pcbEncoded = bytesNeeded;
750 else
752 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
753 pbEncoded, pcbEncoded, bytesNeeded)))
755 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
756 pbEncoded = *(BYTE **)pbEncoded;
757 *pbEncoded++ = ASN_SEQUENCEOF;
758 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
759 pbEncoded += lenBytes;
760 for (i = 0; i < exts->cExtension; i++)
762 DWORD size = dataLen;
764 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
765 pbEncoded, &size);
766 pbEncoded += size;
767 dataLen -= size;
773 __EXCEPT_PAGE_FAULT
775 SetLastError(STATUS_ACCESS_VIOLATION);
776 ret = FALSE;
778 __ENDTRY
779 return ret;
782 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
783 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
784 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
786 LPCSTR pszObjId = (LPCSTR)pvStructInfo;
787 DWORD bytesNeeded = 0, lenBytes;
788 BOOL ret = TRUE;
789 int firstPos = 0;
790 BYTE firstByte = 0;
792 TRACE("%s\n", debugstr_a(pszObjId));
794 if (pszObjId)
796 const char *ptr;
797 int val1, val2;
799 if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
801 SetLastError(CRYPT_E_ASN1_ERROR);
802 return FALSE;
804 bytesNeeded++;
805 firstByte = val1 * 40 + val2;
806 ptr = pszObjId + firstPos;
807 while (ret && *ptr)
809 int pos;
811 /* note I assume each component is at most 32-bits long in base 2 */
812 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
814 if (val1 >= 0x10000000)
815 bytesNeeded += 5;
816 else if (val1 >= 0x200000)
817 bytesNeeded += 4;
818 else if (val1 >= 0x4000)
819 bytesNeeded += 3;
820 else if (val1 >= 0x80)
821 bytesNeeded += 2;
822 else
823 bytesNeeded += 1;
824 ptr += pos;
825 if (*ptr == '.')
826 ptr++;
828 else
830 SetLastError(CRYPT_E_ASN1_ERROR);
831 return FALSE;
834 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
836 else
837 lenBytes = 1;
838 bytesNeeded += 1 + lenBytes;
839 if (pbEncoded)
841 if (*pcbEncoded < bytesNeeded)
843 SetLastError(ERROR_MORE_DATA);
844 ret = FALSE;
846 else
848 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
849 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
850 pbEncoded += lenBytes;
851 if (pszObjId)
853 const char *ptr;
854 int val, pos;
856 *pbEncoded++ = firstByte;
857 ptr = pszObjId + firstPos;
858 while (ret && *ptr)
860 sscanf(ptr, "%d%n", &val, &pos);
862 unsigned char outBytes[5];
863 int numBytes, i;
865 if (val >= 0x10000000)
866 numBytes = 5;
867 else if (val >= 0x200000)
868 numBytes = 4;
869 else if (val >= 0x4000)
870 numBytes = 3;
871 else if (val >= 0x80)
872 numBytes = 2;
873 else
874 numBytes = 1;
875 for (i = numBytes; i > 0; i--)
877 outBytes[i - 1] = val & 0x7f;
878 val >>= 7;
880 for (i = 0; i < numBytes - 1; i++)
881 *pbEncoded++ = outBytes[i] | 0x80;
882 *pbEncoded++ = outBytes[i];
883 ptr += pos;
884 if (*ptr == '.')
885 ptr++;
891 *pcbEncoded = bytesNeeded;
892 return ret;
895 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
896 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
897 DWORD *pcbEncoded)
899 BOOL ret = TRUE;
900 LPCSTR str = (LPCSTR)value->Value.pbData;
901 DWORD bytesNeeded, lenBytes, encodedLen;
903 encodedLen = value->Value.cbData ? value->Value.cbData : strlen(str);
904 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
905 bytesNeeded = 1 + lenBytes + encodedLen;
906 if (!pbEncoded)
907 *pcbEncoded = bytesNeeded;
908 else
910 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
911 pbEncoded, pcbEncoded, bytesNeeded)))
913 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
914 pbEncoded = *(BYTE **)pbEncoded;
915 *pbEncoded++ = tag;
916 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
917 pbEncoded += lenBytes;
918 memcpy(pbEncoded, str, encodedLen);
921 return ret;
924 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
925 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
926 DWORD *pcbEncoded)
928 BOOL ret = TRUE;
929 LPCWSTR str = (LPCWSTR)value->Value.pbData;
930 DWORD bytesNeeded, lenBytes, strLen;
932 if (value->Value.cbData)
933 strLen = value->Value.cbData / sizeof(WCHAR);
934 else if (value->Value.pbData)
935 strLen = lstrlenW(str);
936 else
937 strLen = 0;
938 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
939 bytesNeeded = 1 + lenBytes + strLen * 2;
940 if (!pbEncoded)
941 *pcbEncoded = bytesNeeded;
942 else
944 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
945 pbEncoded, pcbEncoded, bytesNeeded)))
947 DWORD i;
949 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
950 pbEncoded = *(BYTE **)pbEncoded;
951 *pbEncoded++ = ASN_BMPSTRING;
952 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
953 pbEncoded += lenBytes;
954 for (i = 0; i < strLen; i++)
956 *pbEncoded++ = (str[i] & 0xff00) >> 8;
957 *pbEncoded++ = str[i] & 0x00ff;
961 return ret;
964 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
965 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
966 DWORD *pcbEncoded)
968 BOOL ret = TRUE;
969 LPCWSTR str = (LPCWSTR)value->Value.pbData;
970 DWORD bytesNeeded, lenBytes, encodedLen, strLen;
972 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
973 strlenW(str);
974 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
975 NULL);
976 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
977 bytesNeeded = 1 + lenBytes + encodedLen;
978 if (!pbEncoded)
979 *pcbEncoded = bytesNeeded;
980 else
982 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
983 pbEncoded, pcbEncoded, bytesNeeded)))
985 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
986 pbEncoded = *(BYTE **)pbEncoded;
987 *pbEncoded++ = ASN_UTF8STRING;
988 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
989 pbEncoded += lenBytes;
990 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
991 bytesNeeded - lenBytes - 1, NULL, NULL);
994 return ret;
997 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
998 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
999 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1001 BOOL ret = TRUE;
1003 __TRY
1005 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1007 switch (value->dwValueType)
1009 case CERT_RDN_ANY_TYPE:
1010 /* explicitly disallowed */
1011 SetLastError(E_INVALIDARG);
1012 ret = FALSE;
1013 break;
1014 case CERT_RDN_ENCODED_BLOB:
1015 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
1016 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1017 break;
1018 case CERT_RDN_OCTET_STRING:
1019 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1020 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1021 break;
1022 case CERT_RDN_NUMERIC_STRING:
1023 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1024 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1025 break;
1026 case CERT_RDN_PRINTABLE_STRING:
1027 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1028 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1029 break;
1030 case CERT_RDN_TELETEX_STRING:
1031 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1032 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1033 break;
1034 case CERT_RDN_VIDEOTEX_STRING:
1035 ret = CRYPT_AsnEncodeStringCoerce(value,
1036 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1037 break;
1038 case CERT_RDN_IA5_STRING:
1039 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1040 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1041 break;
1042 case CERT_RDN_GRAPHIC_STRING:
1043 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1044 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1045 break;
1046 case CERT_RDN_VISIBLE_STRING:
1047 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1048 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1049 break;
1050 case CERT_RDN_GENERAL_STRING:
1051 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1052 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1053 break;
1054 case CERT_RDN_UNIVERSAL_STRING:
1055 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1056 SetLastError(CRYPT_E_ASN1_CHOICE);
1057 ret = FALSE;
1058 break;
1059 case CERT_RDN_BMP_STRING:
1060 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1061 pbEncoded, pcbEncoded);
1062 break;
1063 case CERT_RDN_UTF8_STRING:
1064 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1065 pbEncoded, pcbEncoded);
1066 break;
1067 default:
1068 SetLastError(CRYPT_E_ASN1_CHOICE);
1069 ret = FALSE;
1072 __EXCEPT_PAGE_FAULT
1074 SetLastError(STATUS_ACCESS_VIOLATION);
1075 ret = FALSE;
1077 __ENDTRY
1078 return ret;
1081 static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1082 CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1083 BYTE *pbEncoded, DWORD *pcbEncoded)
1085 DWORD bytesNeeded = 0, lenBytes, size;
1086 BOOL ret;
1088 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1089 0, NULL, NULL, &size);
1090 if (ret)
1092 bytesNeeded += size;
1093 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1094 * with dwValueType, so "cast" it to get its encoded size
1096 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1097 (CERT_NAME_VALUE *)&attr->dwValueType, 0, NULL, NULL, &size);
1098 if (ret)
1100 bytesNeeded += size;
1101 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1102 bytesNeeded += 1 + lenBytes;
1103 if (pbEncoded)
1105 if (*pcbEncoded < bytesNeeded)
1107 SetLastError(ERROR_MORE_DATA);
1108 ret = FALSE;
1110 else
1112 *pbEncoded++ = ASN_SEQUENCE;
1113 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1114 &lenBytes);
1115 pbEncoded += lenBytes;
1116 size = bytesNeeded - 1 - lenBytes;
1117 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1118 attr->pszObjId, 0, NULL, pbEncoded, &size);
1119 if (ret)
1121 pbEncoded += size;
1122 size = bytesNeeded - 1 - lenBytes - size;
1123 ret = nameValueEncodeFunc(dwCertEncodingType,
1124 NULL, (CERT_NAME_VALUE *)&attr->dwValueType,
1125 0, NULL, pbEncoded, &size);
1126 if (!ret)
1127 *pcbEncoded = size;
1131 if (ret)
1132 *pcbEncoded = bytesNeeded;
1134 else
1136 /* Have to propagate index of failing character */
1137 *pcbEncoded = size;
1140 return ret;
1143 static int BLOBComp(const void *l, const void *r)
1145 const CRYPT_DER_BLOB *a = (const CRYPT_DER_BLOB *)l, *b = (const CRYPT_DER_BLOB *)r;
1146 int ret;
1148 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1149 ret = a->cbData - b->cbData;
1150 return ret;
1153 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1155 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1156 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1157 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1159 const CRYPT_BLOB_ARRAY *set = (const CRYPT_BLOB_ARRAY *)pvStructInfo;
1160 DWORD bytesNeeded = 0, lenBytes, i;
1161 BOOL ret;
1163 for (i = 0; i < set->cBlob; i++)
1164 bytesNeeded += set->rgBlob[i].cbData;
1165 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1166 bytesNeeded += 1 + lenBytes;
1167 if (!pbEncoded)
1169 *pcbEncoded = bytesNeeded;
1170 ret = TRUE;
1172 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1173 pbEncoded, pcbEncoded, bytesNeeded)))
1175 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1176 pbEncoded = *(BYTE **)pbEncoded;
1177 qsort(set->rgBlob, set->cBlob, sizeof(CRYPT_DER_BLOB), BLOBComp);
1178 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1179 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1180 pbEncoded += lenBytes;
1181 for (i = 0; ret && i < set->cBlob; i++)
1183 memcpy(pbEncoded, set->rgBlob[i].pbData, set->rgBlob[i].cbData);
1184 pbEncoded += set->rgBlob[i].cbData;
1187 return ret;
1190 struct DERSetDescriptor
1192 DWORD cItems;
1193 const void *items;
1194 size_t itemSize;
1195 size_t itemOffset;
1196 CryptEncodeObjectExFunc encode;
1199 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,
1200 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1201 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1203 const struct DERSetDescriptor *desc =
1204 (const struct DERSetDescriptor *)pvStructInfo;
1205 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1206 BOOL ret = TRUE;
1207 DWORD i;
1209 if (desc->cItems)
1211 setOf.rgBlob = CryptMemAlloc(desc->cItems * sizeof(CRYPT_DER_BLOB));
1212 if (!setOf.rgBlob)
1213 ret = FALSE;
1214 else
1216 setOf.cBlob = desc->cItems;
1217 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1220 for (i = 0; ret && i < setOf.cBlob; i++)
1222 ret = desc->encode(dwCertEncodingType, lpszStructType,
1223 (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
1224 0, NULL, NULL, &setOf.rgBlob[i].cbData);
1225 if (ret)
1227 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1228 if (!setOf.rgBlob[i].pbData)
1229 ret = FALSE;
1230 else
1231 ret = desc->encode(dwCertEncodingType, lpszStructType,
1232 (const BYTE *)desc->items + i * desc->itemSize +
1233 desc->itemOffset, 0, NULL, setOf.rgBlob[i].pbData,
1234 &setOf.rgBlob[i].cbData);
1236 /* Some functions propagate their errors through the size */
1237 if (!ret)
1238 *pcbEncoded = setOf.rgBlob[i].cbData;
1240 if (ret)
1242 DWORD bytesNeeded = 0, lenBytes;
1244 for (i = 0; i < setOf.cBlob; i++)
1245 bytesNeeded += setOf.rgBlob[i].cbData;
1246 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1247 bytesNeeded += 1 + lenBytes;
1248 if (!pbEncoded)
1249 *pcbEncoded = bytesNeeded;
1250 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1251 pbEncoded, pcbEncoded, bytesNeeded)))
1253 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1254 pbEncoded = *(BYTE **)pbEncoded;
1255 qsort(setOf.rgBlob, setOf.cBlob, sizeof(CRYPT_DER_BLOB),
1256 BLOBComp);
1257 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1258 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1259 pbEncoded += lenBytes;
1260 for (i = 0; i < setOf.cBlob; i++)
1262 memcpy(pbEncoded, setOf.rgBlob[i].pbData,
1263 setOf.rgBlob[i].cbData);
1264 pbEncoded += setOf.rgBlob[i].cbData;
1268 for (i = 0; i < setOf.cBlob; i++)
1269 CryptMemFree(setOf.rgBlob[i].pbData);
1270 CryptMemFree(setOf.rgBlob);
1271 return ret;
1274 static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
1275 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1276 DWORD *pcbEncoded)
1278 BOOL ret;
1279 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1281 __TRY
1283 DWORD i;
1285 ret = TRUE;
1286 if (rdn->cRDNAttr)
1288 setOf.cBlob = rdn->cRDNAttr;
1289 setOf.rgBlob = CryptMemAlloc(rdn->cRDNAttr *
1290 sizeof(CRYPT_DER_BLOB));
1291 if (!setOf.rgBlob)
1292 ret = FALSE;
1293 else
1294 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1296 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1298 setOf.rgBlob[i].cbData = 0;
1299 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1300 nameValueEncodeFunc, NULL, &setOf.rgBlob[i].cbData);
1301 if (ret)
1303 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1304 if (!setOf.rgBlob[i].pbData)
1305 ret = FALSE;
1306 else
1307 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1308 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1309 setOf.rgBlob[i].pbData, &setOf.rgBlob[i].cbData);
1311 if (!ret)
1313 /* Have to propagate index of failing character */
1314 *pcbEncoded = setOf.rgBlob[i].cbData;
1317 if (ret)
1318 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1319 pbEncoded, pcbEncoded);
1320 for (i = 0; i < setOf.cBlob; i++)
1321 CryptMemFree(setOf.rgBlob[i].pbData);
1323 __EXCEPT_PAGE_FAULT
1325 SetLastError(STATUS_ACCESS_VIOLATION);
1326 ret = FALSE;
1328 __ENDTRY
1329 CryptMemFree(setOf.rgBlob);
1330 return ret;
1333 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1334 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1335 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1337 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1338 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1339 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1340 DWORD *pcbEncoded)
1342 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1343 BOOL ret;
1345 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1346 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1347 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1348 else
1349 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1350 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1351 return ret;
1354 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1355 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1356 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1358 BOOL ret = TRUE;
1360 __TRY
1362 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1363 DWORD bytesNeeded = 0, lenBytes, size, i;
1365 TRACE("encoding name with %d RDNs\n", info->cRDN);
1366 ret = TRUE;
1367 for (i = 0; ret && i < info->cRDN; i++)
1369 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1370 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1371 if (ret)
1372 bytesNeeded += size;
1373 else
1374 *pcbEncoded = size;
1376 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1377 bytesNeeded += 1 + lenBytes;
1378 if (ret)
1380 if (!pbEncoded)
1381 *pcbEncoded = bytesNeeded;
1382 else
1384 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1385 pbEncoded, pcbEncoded, bytesNeeded)))
1387 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1388 pbEncoded = *(BYTE **)pbEncoded;
1389 *pbEncoded++ = ASN_SEQUENCEOF;
1390 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1391 &lenBytes);
1392 pbEncoded += lenBytes;
1393 for (i = 0; ret && i < info->cRDN; i++)
1395 size = bytesNeeded;
1396 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1397 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1398 pbEncoded, &size);
1399 if (ret)
1401 pbEncoded += size;
1402 bytesNeeded -= size;
1404 else
1405 *pcbEncoded = size;
1411 __EXCEPT_PAGE_FAULT
1413 SetLastError(STATUS_ACCESS_VIOLATION);
1414 ret = FALSE;
1416 __ENDTRY
1417 return ret;
1420 static BOOL WINAPI CRYPT_AsnEncodeCTLVersion(DWORD dwCertEncodingType,
1421 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1422 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1424 const DWORD *ver = (const DWORD *)pvStructInfo;
1425 BOOL ret;
1427 /* CTL_V1 is not encoded */
1428 if (*ver == CTL_V1)
1430 *pcbEncoded = 0;
1431 ret = TRUE;
1433 else
1434 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
1435 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1436 return ret;
1439 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
1440 * if they are empty and the OID is not empty (otherwise omits them.)
1442 static BOOL WINAPI CRYPT_AsnEncodeCTLSubjectAlgorithm(
1443 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1444 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1445 DWORD *pcbEncoded)
1447 const CRYPT_ALGORITHM_IDENTIFIER *algo =
1448 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1449 BOOL ret;
1450 struct AsnEncodeSequenceItem items[2] = {
1451 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
1453 DWORD cItem = 1;
1455 if (algo->pszObjId)
1457 static const BYTE asn1Null[] = { ASN_NULL, 0 };
1458 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
1459 (LPBYTE)asn1Null };
1461 if (algo->Parameters.cbData)
1462 items[cItem].pvStructInfo = &algo->Parameters;
1463 else
1464 items[cItem].pvStructInfo = &nullBlob;
1465 items[cItem].encodeFunc = CRYPT_CopyEncodedBlob;
1466 cItem++;
1468 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1469 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1470 return ret;
1473 static BOOL WINAPI CRYPT_AsnEncodeCTLEntry(const CTL_ENTRY *entry,
1474 BYTE *pbEncoded, DWORD *pcbEncoded)
1476 struct AsnEncodeSequenceItem items[2] = {
1477 { &entry->SubjectIdentifier, CRYPT_AsnEncodeOctets, 0 },
1478 { &entry->cAttribute, CRYPT_AsnEncodePKCSAttributes, 0 },
1480 BOOL ret;
1482 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1483 sizeof(items) / sizeof(items[0]), 0, NULL, pbEncoded, pcbEncoded);
1484 return ret;
1487 struct CTLEntries
1489 DWORD cEntry;
1490 CTL_ENTRY *rgEntry;
1493 static BOOL WINAPI CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType,
1494 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1495 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1497 BOOL ret;
1498 DWORD bytesNeeded, dataLen, lenBytes, i;
1499 const struct CTLEntries *entries = (const struct CTLEntries *)pvStructInfo;
1501 ret = TRUE;
1502 for (i = 0, dataLen = 0; ret && i < entries->cEntry; i++)
1504 DWORD size;
1506 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i], NULL, &size);
1507 if (ret)
1508 dataLen += size;
1510 if (ret)
1512 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1513 bytesNeeded = 1 + lenBytes + dataLen;
1514 if (!pbEncoded)
1515 *pcbEncoded = bytesNeeded;
1516 else
1518 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1519 pbEncoded, pcbEncoded, bytesNeeded)))
1521 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1522 pbEncoded = *(BYTE **)pbEncoded;
1523 *pbEncoded++ = ASN_SEQUENCEOF;
1524 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1525 pbEncoded += lenBytes;
1526 for (i = 0; ret && i < entries->cEntry; i++)
1528 DWORD size = dataLen;
1530 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i],
1531 pbEncoded, &size);
1532 pbEncoded += size;
1533 dataLen -= size;
1538 return ret;
1541 static BOOL WINAPI CRYPT_AsnEncodeCTL(DWORD dwCertEncodingType,
1542 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1543 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1545 BOOL ret = FALSE;
1547 __TRY
1549 const CTL_INFO *info = (const CTL_INFO *)pvStructInfo;
1550 struct AsnEncodeSequenceItem items[9] = {
1551 { &info->dwVersion, CRYPT_AsnEncodeCTLVersion, 0 },
1552 { &info->SubjectUsage, CRYPT_AsnEncodeEnhancedKeyUsage, 0 },
1554 struct AsnConstructedItem constructed = { 0 };
1555 DWORD cItem = 2;
1557 if (info->ListIdentifier.cbData)
1559 items[cItem].pvStructInfo = &info->ListIdentifier;
1560 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
1561 cItem++;
1563 if (info->SequenceNumber.cbData)
1565 items[cItem].pvStructInfo = &info->SequenceNumber;
1566 items[cItem].encodeFunc = CRYPT_AsnEncodeInteger;
1567 cItem++;
1569 items[cItem].pvStructInfo = &info->ThisUpdate;
1570 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1571 cItem++;
1572 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
1574 items[cItem].pvStructInfo = &info->NextUpdate;
1575 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1576 cItem++;
1578 items[cItem].pvStructInfo = &info->SubjectAlgorithm;
1579 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLSubjectAlgorithm;
1580 cItem++;
1581 if (info->cCTLEntry)
1583 items[cItem].pvStructInfo = &info->cCTLEntry;
1584 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLEntries;
1585 cItem++;
1587 if (info->cExtension)
1589 constructed.tag = 0;
1590 constructed.pvStructInfo = &info->cExtension;
1591 constructed.encodeFunc = CRYPT_AsnEncodeExtensions;
1592 items[cItem].pvStructInfo = &constructed;
1593 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1594 cItem++;
1596 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1597 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1599 __EXCEPT_PAGE_FAULT
1601 SetLastError(STATUS_ACCESS_VIOLATION);
1603 __ENDTRY
1604 return ret;
1607 static BOOL WINAPI CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType,
1608 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1609 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1611 BOOL ret = FALSE;
1613 __TRY
1615 const CRYPT_SMIME_CAPABILITY *capability =
1616 (const CRYPT_SMIME_CAPABILITY *)pvStructInfo;
1618 if (!capability->pszObjId)
1619 SetLastError(E_INVALIDARG);
1620 else
1622 struct AsnEncodeSequenceItem items[] = {
1623 { capability->pszObjId, CRYPT_AsnEncodeOid, 0 },
1624 { &capability->Parameters, CRYPT_CopyEncodedBlob, 0 },
1627 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1628 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1629 pcbEncoded);
1632 __EXCEPT_PAGE_FAULT
1634 SetLastError(STATUS_ACCESS_VIOLATION);
1636 __ENDTRY
1637 return ret;
1640 static BOOL WINAPI CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType,
1641 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1642 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1644 BOOL ret = FALSE;
1646 __TRY
1648 DWORD bytesNeeded, dataLen, lenBytes, i;
1649 const CRYPT_SMIME_CAPABILITIES *capabilities =
1650 (const CRYPT_SMIME_CAPABILITIES *)pvStructInfo;
1652 ret = TRUE;
1653 for (i = 0, dataLen = 0; ret && i < capabilities->cCapability; i++)
1655 DWORD size;
1657 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType, NULL,
1658 &capabilities->rgCapability[i], 0, NULL, NULL, &size);
1659 if (ret)
1660 dataLen += size;
1662 if (ret)
1664 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1665 bytesNeeded = 1 + lenBytes + dataLen;
1666 if (!pbEncoded)
1667 *pcbEncoded = bytesNeeded;
1668 else
1670 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1671 pbEncoded, pcbEncoded, bytesNeeded)))
1673 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1674 pbEncoded = *(BYTE **)pbEncoded;
1675 *pbEncoded++ = ASN_SEQUENCEOF;
1676 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1677 pbEncoded += lenBytes;
1678 for (i = 0; i < capabilities->cCapability; i++)
1680 DWORD size = dataLen;
1682 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType,
1683 NULL, &capabilities->rgCapability[i], 0, NULL,
1684 pbEncoded, &size);
1685 pbEncoded += size;
1686 dataLen -= size;
1692 __EXCEPT_PAGE_FAULT
1694 SetLastError(STATUS_ACCESS_VIOLATION);
1696 __ENDTRY
1697 return ret;
1700 static BOOL WINAPI CRYPT_AsnEncodeNoticeNumbers(DWORD dwCertEncodingType,
1701 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1702 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1704 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
1705 DWORD bytesNeeded, dataLen, lenBytes, i;
1706 BOOL ret = TRUE;
1708 for (i = 0, dataLen = 0; ret && i < noticeRef->cNoticeNumbers; i++)
1710 DWORD size;
1712 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
1713 &noticeRef->rgNoticeNumbers[i], 0, NULL, NULL, &size);
1714 if (ret)
1715 dataLen += size;
1717 if (ret)
1719 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1720 bytesNeeded = 1 + lenBytes + dataLen;
1721 if (!pbEncoded)
1722 *pcbEncoded = bytesNeeded;
1723 else
1725 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1726 pcbEncoded, bytesNeeded)))
1728 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1729 pbEncoded = *(BYTE **)pbEncoded;
1730 *pbEncoded++ = ASN_SEQUENCE;
1731 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1732 pbEncoded += lenBytes;
1733 for (i = 0; i < noticeRef->cNoticeNumbers; i++)
1735 DWORD size = dataLen;
1737 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
1738 &noticeRef->rgNoticeNumbers[i], 0, NULL, pbEncoded, &size);
1739 pbEncoded += size;
1740 dataLen -= size;
1745 return ret;
1748 static BOOL WINAPI CRYPT_AsnEncodeNoticeReference(DWORD dwCertEncodingType,
1749 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1750 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1752 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
1753 BOOL ret;
1754 CERT_NAME_VALUE orgValue = { CERT_RDN_IA5_STRING,
1755 { 0, (LPBYTE)noticeRef->pszOrganization } };
1756 struct AsnEncodeSequenceItem items[] = {
1757 { &orgValue, CRYPT_AsnEncodeNameValue, 0 },
1758 { noticeRef, CRYPT_AsnEncodeNoticeNumbers, 0 },
1761 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1762 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1763 pcbEncoded);
1764 return ret;
1767 static BOOL WINAPI CRYPT_AsnEncodePolicyQualifierUserNotice(
1768 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1769 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1770 DWORD *pcbEncoded)
1772 BOOL ret = FALSE;
1774 __TRY
1776 const CERT_POLICY_QUALIFIER_USER_NOTICE *notice = pvStructInfo;
1777 struct AsnEncodeSequenceItem items[2];
1778 CERT_NAME_VALUE displayTextValue;
1779 DWORD cItem = 0;
1781 ret = TRUE;
1782 if (notice->pNoticeReference)
1784 items[cItem].encodeFunc = CRYPT_AsnEncodeNoticeReference;
1785 items[cItem].pvStructInfo = notice->pNoticeReference;
1786 cItem++;
1788 if (notice->pszDisplayText)
1790 displayTextValue.dwValueType = CERT_RDN_BMP_STRING;
1791 displayTextValue.Value.cbData = 0;
1792 displayTextValue.Value.pbData = (LPBYTE)notice->pszDisplayText;
1793 items[cItem].encodeFunc = CRYPT_AsnEncodeNameValue;
1794 items[cItem].pvStructInfo = &displayTextValue;
1795 cItem++;
1797 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1798 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1800 __EXCEPT_PAGE_FAULT
1802 SetLastError(STATUS_ACCESS_VIOLATION);
1804 __ENDTRY
1805 return ret;
1808 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1809 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1810 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1812 BOOL ret = FALSE;
1814 __TRY
1816 const CRYPT_ATTRIBUTE *attr = (const CRYPT_ATTRIBUTE *)pvStructInfo;
1818 if (!attr->pszObjId)
1819 SetLastError(E_INVALIDARG);
1820 else
1822 struct AsnEncodeSequenceItem items[2] = {
1823 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1824 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1827 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1828 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1829 pcbEncoded);
1832 __EXCEPT_PAGE_FAULT
1834 SetLastError(STATUS_ACCESS_VIOLATION);
1836 __ENDTRY
1837 return ret;
1840 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1841 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1842 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1844 BOOL ret = FALSE;
1846 __TRY
1848 const CRYPT_ATTRIBUTES *attributes =
1849 (const CRYPT_ATTRIBUTES *)pvStructInfo;
1850 struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
1851 sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
1853 ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
1854 &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1856 __EXCEPT_PAGE_FAULT
1858 SetLastError(STATUS_ACCESS_VIOLATION);
1860 __ENDTRY
1861 return ret;
1864 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1865 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
1866 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1867 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1868 DWORD *pcbEncoded)
1870 const CRYPT_CONTENT_INFO *info = (const CRYPT_CONTENT_INFO *)pvStructInfo;
1871 struct AsnEncodeSequenceItem items[2] = {
1872 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1873 { NULL, NULL, 0 },
1875 struct AsnConstructedItem constructed = { 0 };
1876 DWORD cItem = 1;
1878 if (info->Content.cbData)
1880 constructed.tag = 0;
1881 constructed.pvStructInfo = &info->Content;
1882 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1883 items[cItem].pvStructInfo = &constructed;
1884 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1885 cItem++;
1887 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1888 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1891 BOOL CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA *digestedData,
1892 void *pvData, DWORD *pcbData)
1894 struct AsnEncodeSequenceItem items[] = {
1895 { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1896 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
1897 0 },
1898 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1899 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1902 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1903 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
1906 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1907 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1908 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1910 BOOL ret = FALSE;
1912 __TRY
1914 const CRYPT_CONTENT_INFO *info =
1915 (const CRYPT_CONTENT_INFO *)pvStructInfo;
1917 if (!info->pszObjId)
1918 SetLastError(E_INVALIDARG);
1919 else
1920 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
1921 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1922 pcbEncoded);
1924 __EXCEPT_PAGE_FAULT
1926 SetLastError(STATUS_ACCESS_VIOLATION);
1928 __ENDTRY
1929 return ret;
1932 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1933 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1934 DWORD *pcbEncoded)
1936 BOOL ret = TRUE;
1937 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1938 DWORD bytesNeeded, lenBytes, encodedLen;
1940 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1941 strlenW(str);
1942 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1943 bytesNeeded = 1 + lenBytes + encodedLen;
1944 if (!pbEncoded)
1945 *pcbEncoded = bytesNeeded;
1946 else
1948 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1949 pbEncoded, pcbEncoded, bytesNeeded)))
1951 DWORD i;
1953 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1954 pbEncoded = *(BYTE **)pbEncoded;
1955 *pbEncoded++ = tag;
1956 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1957 pbEncoded += lenBytes;
1958 for (i = 0; i < encodedLen; i++)
1959 *pbEncoded++ = (BYTE)str[i];
1962 return ret;
1965 static void CRYPT_FreeSpace(PCRYPT_ENCODE_PARA pEncodePara, LPVOID pv)
1967 if (pEncodePara && pEncodePara->pfnFree)
1968 pEncodePara->pfnFree(pv);
1969 else
1970 LocalFree(pv);
1973 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
1974 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1975 DWORD *pcbEncoded)
1977 BOOL ret = TRUE;
1978 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1979 DWORD bytesNeeded, lenBytes, encodedLen;
1981 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1982 strlenW(str);
1983 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1984 bytesNeeded = 1 + lenBytes + encodedLen;
1985 if (!pbEncoded)
1986 *pcbEncoded = bytesNeeded;
1987 else
1989 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1990 pbEncoded, pcbEncoded, bytesNeeded)))
1992 DWORD i;
1993 BYTE *ptr;
1995 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1996 ptr = *(BYTE **)pbEncoded;
1997 else
1998 ptr = pbEncoded;
1999 *ptr++ = ASN_NUMERICSTRING;
2000 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2001 ptr += lenBytes;
2002 for (i = 0; ret && i < encodedLen; i++)
2004 if (isdigitW(str[i]))
2005 *ptr++ = (BYTE)str[i];
2006 else
2008 *pcbEncoded = i;
2009 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
2010 ret = FALSE;
2013 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2014 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2017 return ret;
2020 static inline int isprintableW(WCHAR wc)
2022 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
2023 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
2024 wc == '/' || wc == ':' || wc == '=' || wc == '?';
2027 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
2028 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
2029 DWORD *pcbEncoded)
2031 BOOL ret = TRUE;
2032 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2033 DWORD bytesNeeded, lenBytes, encodedLen;
2035 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
2036 strlenW(str);
2037 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2038 bytesNeeded = 1 + lenBytes + encodedLen;
2039 if (!pbEncoded)
2040 *pcbEncoded = bytesNeeded;
2041 else
2043 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2044 pbEncoded, pcbEncoded, bytesNeeded)))
2046 DWORD i;
2047 BYTE *ptr;
2049 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2050 ptr = *(BYTE **)pbEncoded;
2051 else
2052 ptr = pbEncoded;
2053 *ptr++ = ASN_PRINTABLESTRING;
2054 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2055 ptr += lenBytes;
2056 for (i = 0; ret && i < encodedLen; i++)
2058 if (isprintableW(str[i]))
2059 *ptr++ = (BYTE)str[i];
2060 else
2062 *pcbEncoded = i;
2063 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
2064 ret = FALSE;
2067 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2068 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2071 return ret;
2074 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
2075 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
2076 DWORD *pcbEncoded)
2078 BOOL ret = TRUE;
2079 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2080 DWORD bytesNeeded, lenBytes, encodedLen;
2082 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
2083 strlenW(str);
2084 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2085 bytesNeeded = 1 + lenBytes + encodedLen;
2086 if (!pbEncoded)
2087 *pcbEncoded = bytesNeeded;
2088 else
2090 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2091 pbEncoded, pcbEncoded, bytesNeeded)))
2093 DWORD i;
2094 BYTE *ptr;
2096 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2097 ptr = *(BYTE **)pbEncoded;
2098 else
2099 ptr = pbEncoded;
2100 *ptr++ = ASN_IA5STRING;
2101 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2102 ptr += lenBytes;
2103 for (i = 0; ret && i < encodedLen; i++)
2105 if (str[i] <= 0x7f)
2106 *ptr++ = (BYTE)str[i];
2107 else
2109 *pcbEncoded = i;
2110 SetLastError(CRYPT_E_INVALID_IA5_STRING);
2111 ret = FALSE;
2114 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2115 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2118 return ret;
2121 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
2122 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
2123 DWORD *pcbEncoded)
2125 BOOL ret = TRUE;
2126 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2127 DWORD bytesNeeded, lenBytes, strLen;
2129 /* FIXME: doesn't handle composite characters */
2130 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
2131 strlenW(str);
2132 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
2133 bytesNeeded = 1 + lenBytes + strLen * 4;
2134 if (!pbEncoded)
2135 *pcbEncoded = bytesNeeded;
2136 else
2138 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2139 pbEncoded, pcbEncoded, bytesNeeded)))
2141 DWORD i;
2143 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2144 pbEncoded = *(BYTE **)pbEncoded;
2145 *pbEncoded++ = ASN_UNIVERSALSTRING;
2146 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
2147 pbEncoded += lenBytes;
2148 for (i = 0; i < strLen; i++)
2150 *pbEncoded++ = 0;
2151 *pbEncoded++ = 0;
2152 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
2153 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
2157 return ret;
2160 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
2161 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2162 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2164 BOOL ret = FALSE;
2166 __TRY
2168 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
2170 switch (value->dwValueType)
2172 case CERT_RDN_ANY_TYPE:
2173 case CERT_RDN_ENCODED_BLOB:
2174 case CERT_RDN_OCTET_STRING:
2175 SetLastError(CRYPT_E_NOT_CHAR_STRING);
2176 break;
2177 case CERT_RDN_NUMERIC_STRING:
2178 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
2179 pbEncoded, pcbEncoded);
2180 break;
2181 case CERT_RDN_PRINTABLE_STRING:
2182 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
2183 pbEncoded, pcbEncoded);
2184 break;
2185 case CERT_RDN_TELETEX_STRING:
2186 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
2187 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2188 break;
2189 case CERT_RDN_VIDEOTEX_STRING:
2190 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
2191 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2192 break;
2193 case CERT_RDN_IA5_STRING:
2194 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
2195 pbEncoded, pcbEncoded);
2196 break;
2197 case CERT_RDN_GRAPHIC_STRING:
2198 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
2199 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2200 break;
2201 case CERT_RDN_VISIBLE_STRING:
2202 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
2203 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2204 break;
2205 case CERT_RDN_GENERAL_STRING:
2206 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
2207 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2208 break;
2209 case CERT_RDN_UNIVERSAL_STRING:
2210 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
2211 pbEncoded, pcbEncoded);
2212 break;
2213 case CERT_RDN_BMP_STRING:
2214 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
2215 pbEncoded, pcbEncoded);
2216 break;
2217 case CERT_RDN_UTF8_STRING:
2218 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
2219 pbEncoded, pcbEncoded);
2220 break;
2221 default:
2222 SetLastError(CRYPT_E_ASN1_CHOICE);
2225 __EXCEPT_PAGE_FAULT
2227 SetLastError(STATUS_ACCESS_VIOLATION);
2229 __ENDTRY
2230 return ret;
2233 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
2234 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2235 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2237 BOOL ret;
2239 __TRY
2241 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
2242 DWORD bytesNeeded = 0, lenBytes, size, i;
2244 TRACE("encoding name with %d RDNs\n", info->cRDN);
2245 ret = TRUE;
2246 for (i = 0; ret && i < info->cRDN; i++)
2248 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
2249 CRYPT_AsnEncodeNameValue, NULL, &size);
2250 if (ret)
2251 bytesNeeded += size;
2253 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2254 bytesNeeded += 1 + lenBytes;
2255 if (ret)
2257 if (!pbEncoded)
2258 *pcbEncoded = bytesNeeded;
2259 else
2261 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2262 pbEncoded, pcbEncoded, bytesNeeded)))
2264 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2265 pbEncoded = *(BYTE **)pbEncoded;
2266 *pbEncoded++ = ASN_SEQUENCEOF;
2267 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
2268 &lenBytes);
2269 pbEncoded += lenBytes;
2270 for (i = 0; ret && i < info->cRDN; i++)
2272 size = bytesNeeded;
2273 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
2274 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, pbEncoded,
2275 &size);
2276 if (ret)
2278 pbEncoded += size;
2279 bytesNeeded -= size;
2286 __EXCEPT_PAGE_FAULT
2288 SetLastError(STATUS_ACCESS_VIOLATION);
2289 ret = FALSE;
2291 __ENDTRY
2292 return ret;
2295 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
2296 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2297 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2299 BOOL val = *(const BOOL *)pvStructInfo, ret;
2301 TRACE("%d\n", val);
2303 if (!pbEncoded)
2305 *pcbEncoded = 3;
2306 ret = TRUE;
2308 else if (*pcbEncoded < 3)
2310 *pcbEncoded = 3;
2311 SetLastError(ERROR_MORE_DATA);
2312 ret = FALSE;
2314 else
2316 *pcbEncoded = 3;
2317 *pbEncoded++ = ASN_BOOL;
2318 *pbEncoded++ = 1;
2319 *pbEncoded++ = val ? 0xff : 0;
2320 ret = TRUE;
2322 TRACE("returning %d (%08x)\n", ret, GetLastError());
2323 return ret;
2326 static BOOL WINAPI CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType,
2327 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2328 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2330 const CERT_ALT_NAME_ENTRY *entry =
2331 (const CERT_ALT_NAME_ENTRY *)pvStructInfo;
2332 BOOL ret;
2333 DWORD dataLen;
2334 BYTE tag;
2336 ret = TRUE;
2337 switch (entry->dwAltNameChoice)
2339 case CERT_ALT_NAME_RFC822_NAME:
2340 case CERT_ALT_NAME_DNS_NAME:
2341 case CERT_ALT_NAME_URL:
2342 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2343 if (entry->u.pwszURL)
2345 DWORD i;
2347 /* Not + 1: don't encode the NULL-terminator */
2348 dataLen = lstrlenW(entry->u.pwszURL);
2349 for (i = 0; ret && i < dataLen; i++)
2351 if (entry->u.pwszURL[i] > 0x7f)
2353 SetLastError(CRYPT_E_INVALID_IA5_STRING);
2354 ret = FALSE;
2355 *pcbEncoded = i;
2359 else
2360 dataLen = 0;
2361 break;
2362 case CERT_ALT_NAME_DIRECTORY_NAME:
2363 tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1);
2364 dataLen = entry->u.DirectoryName.cbData;
2365 break;
2366 case CERT_ALT_NAME_IP_ADDRESS:
2367 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2368 dataLen = entry->u.IPAddress.cbData;
2369 break;
2370 case CERT_ALT_NAME_REGISTERED_ID:
2372 struct AsnEncodeTagSwappedItem swapped =
2373 { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID,
2374 CRYPT_AsnEncodeOid };
2376 return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded,
2377 pcbEncoded);
2379 case CERT_ALT_NAME_OTHER_NAME:
2380 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
2381 return FALSE;
2382 default:
2383 SetLastError(E_INVALIDARG);
2384 return FALSE;
2386 if (ret)
2388 DWORD bytesNeeded, lenBytes;
2390 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2391 bytesNeeded = 1 + dataLen + lenBytes;
2392 if (!pbEncoded)
2393 *pcbEncoded = bytesNeeded;
2394 else if (*pcbEncoded < bytesNeeded)
2396 SetLastError(ERROR_MORE_DATA);
2397 *pcbEncoded = bytesNeeded;
2398 ret = FALSE;
2400 else
2402 *pbEncoded++ = tag;
2403 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2404 pbEncoded += lenBytes;
2405 switch (entry->dwAltNameChoice)
2407 case CERT_ALT_NAME_RFC822_NAME:
2408 case CERT_ALT_NAME_DNS_NAME:
2409 case CERT_ALT_NAME_URL:
2411 DWORD i;
2413 for (i = 0; i < dataLen; i++)
2414 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
2415 break;
2417 case CERT_ALT_NAME_DIRECTORY_NAME:
2418 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen);
2419 break;
2420 case CERT_ALT_NAME_IP_ADDRESS:
2421 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
2422 break;
2424 if (ret)
2425 *pcbEncoded = bytesNeeded;
2428 TRACE("returning %d (%08x)\n", ret, GetLastError());
2429 return ret;
2432 static BOOL WINAPI CRYPT_AsnEncodeIntegerSwapBytes(DWORD dwCertEncodingType,
2433 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2434 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2436 BOOL ret;
2438 __TRY
2440 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2441 CRYPT_DATA_BLOB newBlob = { blob->cbData, NULL };
2443 ret = TRUE;
2444 if (newBlob.cbData)
2446 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2447 if (newBlob.pbData)
2449 DWORD i;
2451 for (i = 0; i < newBlob.cbData; i++)
2452 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2454 else
2455 ret = FALSE;
2457 if (ret)
2458 ret = CRYPT_AsnEncodeInteger(dwCertEncodingType, lpszStructType,
2459 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2460 CryptMemFree(newBlob.pbData);
2462 __EXCEPT_PAGE_FAULT
2464 SetLastError(STATUS_ACCESS_VIOLATION);
2465 ret = FALSE;
2467 __ENDTRY
2468 return ret;
2471 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
2472 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2473 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2475 BOOL ret;
2477 __TRY
2479 const CERT_AUTHORITY_KEY_ID_INFO *info =
2480 (const CERT_AUTHORITY_KEY_ID_INFO *)pvStructInfo;
2481 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2482 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2483 struct AsnConstructedItem constructed = { 0 };
2484 DWORD cItem = 0, cSwapped = 0;
2486 if (info->KeyId.cbData)
2488 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2489 swapped[cSwapped].pvStructInfo = &info->KeyId;
2490 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2491 items[cItem].pvStructInfo = &swapped[cSwapped];
2492 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2493 cSwapped++;
2494 cItem++;
2496 if (info->CertIssuer.cbData)
2498 constructed.tag = 1;
2499 constructed.pvStructInfo = &info->CertIssuer;
2500 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2501 items[cItem].pvStructInfo = &constructed;
2502 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2503 cItem++;
2505 if (info->CertSerialNumber.cbData)
2507 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2508 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2509 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2510 items[cItem].pvStructInfo = &swapped[cSwapped];
2511 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2512 cSwapped++;
2513 cItem++;
2515 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2516 pEncodePara, pbEncoded, pcbEncoded);
2518 __EXCEPT_PAGE_FAULT
2520 SetLastError(STATUS_ACCESS_VIOLATION);
2521 ret = FALSE;
2523 __ENDTRY
2524 return ret;
2527 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2528 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2529 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2531 BOOL ret;
2533 __TRY
2535 const CERT_ALT_NAME_INFO *info =
2536 (const CERT_ALT_NAME_INFO *)pvStructInfo;
2537 DWORD bytesNeeded, dataLen, lenBytes, i;
2539 ret = TRUE;
2540 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2541 * can't encode an erroneous entry index if it's bigger than this.
2543 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2545 DWORD len;
2547 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, NULL,
2548 &info->rgAltEntry[i], 0, NULL, NULL, &len);
2549 if (ret)
2550 dataLen += len;
2551 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2553 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2554 * the bad character, now set the index of the bad
2555 * entry
2557 *pcbEncoded = (BYTE)i <<
2558 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2561 if (ret)
2563 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2564 bytesNeeded = 1 + lenBytes + dataLen;
2565 if (!pbEncoded)
2567 *pcbEncoded = bytesNeeded;
2568 ret = TRUE;
2570 else
2572 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2573 pbEncoded, pcbEncoded, bytesNeeded)))
2575 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2576 pbEncoded = *(BYTE **)pbEncoded;
2577 *pbEncoded++ = ASN_SEQUENCEOF;
2578 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2579 pbEncoded += lenBytes;
2580 for (i = 0; ret && i < info->cAltEntry; i++)
2582 DWORD len = dataLen;
2584 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType,
2585 NULL, &info->rgAltEntry[i], 0, NULL, pbEncoded, &len);
2586 if (ret)
2588 pbEncoded += len;
2589 dataLen -= len;
2596 __EXCEPT_PAGE_FAULT
2598 SetLastError(STATUS_ACCESS_VIOLATION);
2599 ret = FALSE;
2601 __ENDTRY
2602 return ret;
2605 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2606 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2607 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2609 BOOL ret;
2611 __TRY
2613 const CERT_AUTHORITY_KEY_ID2_INFO *info =
2614 (const CERT_AUTHORITY_KEY_ID2_INFO *)pvStructInfo;
2615 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2616 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2617 DWORD cItem = 0, cSwapped = 0;
2619 if (info->KeyId.cbData)
2621 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2622 swapped[cSwapped].pvStructInfo = &info->KeyId;
2623 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2624 items[cItem].pvStructInfo = &swapped[cSwapped];
2625 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2626 cSwapped++;
2627 cItem++;
2629 if (info->AuthorityCertIssuer.cAltEntry)
2631 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2632 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2633 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2634 items[cItem].pvStructInfo = &swapped[cSwapped];
2635 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2636 cSwapped++;
2637 cItem++;
2639 if (info->AuthorityCertSerialNumber.cbData)
2641 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2642 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2643 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2644 items[cItem].pvStructInfo = &swapped[cSwapped];
2645 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2646 cSwapped++;
2647 cItem++;
2649 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2650 pEncodePara, pbEncoded, pcbEncoded);
2652 __EXCEPT_PAGE_FAULT
2654 SetLastError(STATUS_ACCESS_VIOLATION);
2655 ret = FALSE;
2657 __ENDTRY
2658 return ret;
2661 static BOOL WINAPI CRYPT_AsnEncodeAccessDescription(
2662 const CERT_ACCESS_DESCRIPTION *descr, BYTE *pbEncoded, DWORD *pcbEncoded)
2664 struct AsnEncodeSequenceItem items[] = {
2665 { descr->pszAccessMethod, CRYPT_AsnEncodeOid, 0 },
2666 { &descr->AccessLocation, CRYPT_AsnEncodeAltNameEntry, 0 },
2669 if (!descr->pszAccessMethod)
2671 SetLastError(E_INVALIDARG);
2672 return FALSE;
2674 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
2675 sizeof(items) / sizeof(items[0]), 0, NULL, pbEncoded, pcbEncoded);
2678 static BOOL WINAPI CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType,
2679 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2680 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2682 BOOL ret;
2684 __TRY
2686 DWORD bytesNeeded, dataLen, lenBytes, i;
2687 const CERT_AUTHORITY_INFO_ACCESS *info =
2688 (const CERT_AUTHORITY_INFO_ACCESS *)pvStructInfo;
2690 ret = TRUE;
2691 for (i = 0, dataLen = 0; ret && i < info->cAccDescr; i++)
2693 DWORD size;
2695 ret = CRYPT_AsnEncodeAccessDescription(&info->rgAccDescr[i], NULL,
2696 &size);
2697 if (ret)
2698 dataLen += size;
2700 if (ret)
2702 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2703 bytesNeeded = 1 + lenBytes + dataLen;
2704 if (!pbEncoded)
2705 *pcbEncoded = bytesNeeded;
2706 else
2708 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2709 pbEncoded, pcbEncoded, bytesNeeded)))
2711 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2712 pbEncoded = *(BYTE **)pbEncoded;
2713 *pbEncoded++ = ASN_SEQUENCEOF;
2714 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2715 pbEncoded += lenBytes;
2716 for (i = 0; i < info->cAccDescr; i++)
2718 DWORD size = dataLen;
2720 ret = CRYPT_AsnEncodeAccessDescription(
2721 &info->rgAccDescr[i], pbEncoded, &size);
2722 pbEncoded += size;
2723 dataLen -= size;
2729 __EXCEPT_PAGE_FAULT
2731 SetLastError(STATUS_ACCESS_VIOLATION);
2732 ret = FALSE;
2734 __ENDTRY
2735 return ret;
2738 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2739 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2740 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2742 BOOL ret;
2744 __TRY
2746 const CERT_BASIC_CONSTRAINTS_INFO *info =
2747 (const CERT_BASIC_CONSTRAINTS_INFO *)pvStructInfo;
2748 struct AsnEncodeSequenceItem items[3] = {
2749 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2750 { 0 }
2752 DWORD cItem = 1;
2754 if (info->fPathLenConstraint)
2756 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2757 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2758 cItem++;
2760 if (info->cSubtreesConstraint)
2762 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2763 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2764 cItem++;
2766 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2767 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2769 __EXCEPT_PAGE_FAULT
2771 SetLastError(STATUS_ACCESS_VIOLATION);
2772 ret = FALSE;
2774 __ENDTRY
2775 return ret;
2778 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2779 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2780 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2782 BOOL ret;
2784 __TRY
2786 const CERT_BASIC_CONSTRAINTS2_INFO *info =
2787 (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
2788 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2789 DWORD cItem = 0;
2791 if (info->fCA)
2793 items[cItem].pvStructInfo = &info->fCA;
2794 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2795 cItem++;
2797 if (info->fPathLenConstraint)
2799 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2800 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2801 cItem++;
2803 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2804 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2806 __EXCEPT_PAGE_FAULT
2808 SetLastError(STATUS_ACCESS_VIOLATION);
2809 ret = FALSE;
2811 __ENDTRY
2812 return ret;
2815 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType,
2816 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2817 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2819 DWORD cPolicyQualifier = *(DWORD *)pvStructInfo;
2820 const CERT_POLICY_QUALIFIER_INFO *rgPolicyQualifier =
2821 *(const CERT_POLICY_QUALIFIER_INFO **)
2822 ((LPBYTE)pvStructInfo + sizeof(DWORD));
2823 BOOL ret;
2825 if (!cPolicyQualifier)
2827 *pcbEncoded = 0;
2828 ret = TRUE;
2830 else
2832 struct AsnEncodeSequenceItem items[2] = {
2833 { NULL, CRYPT_AsnEncodeOid, 0 },
2834 { NULL, CRYPT_CopyEncodedBlob, 0 },
2836 DWORD bytesNeeded = 0, lenBytes, size, i;
2838 ret = TRUE;
2839 for (i = 0; ret && i < cPolicyQualifier; i++)
2841 items[0].pvStructInfo = rgPolicyQualifier[i].pszPolicyQualifierId;
2842 items[1].pvStructInfo = &rgPolicyQualifier[i].Qualifier;
2843 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2844 sizeof(items) / sizeof(items[0]),
2845 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
2846 if (ret)
2847 bytesNeeded += size;
2849 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2850 bytesNeeded += 1 + lenBytes;
2851 if (ret)
2853 if (!pbEncoded)
2854 *pcbEncoded = bytesNeeded;
2855 else
2857 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2858 pbEncoded, pcbEncoded, bytesNeeded)))
2860 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2861 pbEncoded = *(BYTE **)pbEncoded;
2862 *pbEncoded++ = ASN_SEQUENCEOF;
2863 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
2864 &lenBytes);
2865 pbEncoded += lenBytes;
2866 for (i = 0; ret && i < cPolicyQualifier; i++)
2868 items[0].pvStructInfo =
2869 rgPolicyQualifier[i].pszPolicyQualifierId;
2870 items[1].pvStructInfo =
2871 &rgPolicyQualifier[i].Qualifier;
2872 size = bytesNeeded;
2873 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2874 sizeof(items) / sizeof(items[0]),
2875 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
2876 &size);
2877 if (ret)
2879 pbEncoded += size;
2880 bytesNeeded -= size;
2887 return ret;
2890 static BOOL CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType,
2891 const CERT_POLICY_INFO *info, DWORD dwFlags, BYTE *pbEncoded,
2892 DWORD *pcbEncoded)
2894 struct AsnEncodeSequenceItem items[2] = {
2895 { info->pszPolicyIdentifier, CRYPT_AsnEncodeOid, 0 },
2896 { &info->cPolicyQualifier, CRYPT_AsnEncodeCertPolicyQualifiers, 0 },
2898 BOOL ret;
2900 if (!info->pszPolicyIdentifier)
2902 SetLastError(E_INVALIDARG);
2903 return FALSE;
2905 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2906 sizeof(items) / sizeof(items[0]), dwFlags, NULL, pbEncoded, pcbEncoded);
2907 return ret;
2910 static BOOL WINAPI CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType,
2911 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2912 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2914 BOOL ret = FALSE;
2916 __TRY
2918 const CERT_POLICIES_INFO *info = pvStructInfo;
2919 DWORD bytesNeeded = 0, lenBytes, size, i;
2921 ret = TRUE;
2922 for (i = 0; ret && i < info->cPolicyInfo; i++)
2924 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
2925 &info->rgPolicyInfo[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
2926 &size);
2927 if (ret)
2928 bytesNeeded += size;
2930 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2931 bytesNeeded += 1 + lenBytes;
2932 if (ret)
2934 if (!pbEncoded)
2935 *pcbEncoded = bytesNeeded;
2936 else
2938 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2939 pbEncoded, pcbEncoded, bytesNeeded)))
2941 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2942 pbEncoded = *(BYTE **)pbEncoded;
2943 *pbEncoded++ = ASN_SEQUENCEOF;
2944 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
2945 &lenBytes);
2946 pbEncoded += lenBytes;
2947 for (i = 0; ret && i < info->cPolicyInfo; i++)
2949 size = bytesNeeded;
2950 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
2951 &info->rgPolicyInfo[i],
2952 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pbEncoded, &size);
2953 if (ret)
2955 pbEncoded += size;
2956 bytesNeeded -= size;
2963 __EXCEPT_PAGE_FAULT
2965 SetLastError(STATUS_ACCESS_VIOLATION);
2967 __ENDTRY
2968 return ret;
2971 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
2972 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2973 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2975 BOOL ret;
2977 __TRY
2979 const BLOBHEADER *hdr =
2980 (const BLOBHEADER *)pvStructInfo;
2982 if (hdr->bType != PUBLICKEYBLOB)
2984 SetLastError(E_INVALIDARG);
2985 ret = FALSE;
2987 else
2989 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
2990 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
2991 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
2992 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
2993 struct AsnEncodeSequenceItem items[] = {
2994 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
2995 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
2998 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2999 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3000 pcbEncoded);
3003 __EXCEPT_PAGE_FAULT
3005 SetLastError(STATUS_ACCESS_VIOLATION);
3006 ret = FALSE;
3008 __ENDTRY
3009 return ret;
3012 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
3013 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3014 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3016 BOOL ret;
3018 __TRY
3020 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
3021 DWORD bytesNeeded, lenBytes;
3023 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
3024 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
3026 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
3027 bytesNeeded = 1 + lenBytes + blob->cbData;
3028 if (!pbEncoded)
3030 *pcbEncoded = bytesNeeded;
3031 ret = TRUE;
3033 else
3035 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3036 pcbEncoded, bytesNeeded)))
3038 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3039 pbEncoded = *(BYTE **)pbEncoded;
3040 *pbEncoded++ = ASN_OCTETSTRING;
3041 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
3042 pbEncoded += lenBytes;
3043 if (blob->cbData)
3044 memcpy(pbEncoded, blob->pbData, blob->cbData);
3048 __EXCEPT_PAGE_FAULT
3050 SetLastError(STATUS_ACCESS_VIOLATION);
3051 ret = FALSE;
3053 __ENDTRY
3054 TRACE("returning %d (%08x)\n", ret, GetLastError());
3055 return ret;
3058 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
3059 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3060 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3062 BOOL ret;
3064 __TRY
3066 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
3067 DWORD bytesNeeded, lenBytes, dataBytes;
3068 BYTE unusedBits;
3070 /* yep, MS allows cUnusedBits to be >= 8 */
3071 if (!blob->cUnusedBits)
3073 dataBytes = blob->cbData;
3074 unusedBits = 0;
3076 else if (blob->cbData * 8 > blob->cUnusedBits)
3078 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
3079 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
3080 blob->cUnusedBits;
3082 else
3084 dataBytes = 0;
3085 unusedBits = 0;
3087 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
3088 bytesNeeded = 1 + lenBytes + dataBytes + 1;
3089 if (!pbEncoded)
3091 *pcbEncoded = bytesNeeded;
3092 ret = TRUE;
3094 else
3096 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3097 pcbEncoded, bytesNeeded)))
3099 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3100 pbEncoded = *(BYTE **)pbEncoded;
3101 *pbEncoded++ = ASN_BITSTRING;
3102 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
3103 pbEncoded += lenBytes;
3104 *pbEncoded++ = unusedBits;
3105 if (dataBytes)
3107 BYTE mask = 0xff << unusedBits;
3109 if (dataBytes > 1)
3111 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
3112 pbEncoded += dataBytes - 1;
3114 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
3119 __EXCEPT_PAGE_FAULT
3121 SetLastError(STATUS_ACCESS_VIOLATION);
3122 ret = FALSE;
3124 __ENDTRY
3125 return ret;
3128 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
3129 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3130 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3132 BOOL ret;
3134 __TRY
3136 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
3137 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
3139 ret = TRUE;
3140 if (newBlob.cbData)
3142 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
3143 if (newBlob.pbData)
3145 DWORD i;
3147 for (i = 0; i < newBlob.cbData; i++)
3148 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
3150 else
3151 ret = FALSE;
3153 if (ret)
3154 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
3155 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3156 CryptMemFree(newBlob.pbData);
3158 __EXCEPT_PAGE_FAULT
3160 SetLastError(STATUS_ACCESS_VIOLATION);
3161 ret = FALSE;
3163 __ENDTRY
3164 return ret;
3167 BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
3168 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3169 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3171 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
3173 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
3174 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3177 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
3178 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3179 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3181 BOOL ret;
3183 __TRY
3185 DWORD significantBytes, lenBytes, bytesNeeded;
3186 BYTE padByte = 0;
3187 BOOL pad = FALSE;
3188 const CRYPT_INTEGER_BLOB *blob =
3189 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
3191 significantBytes = blob->cbData;
3192 if (significantBytes)
3194 if (blob->pbData[significantBytes - 1] & 0x80)
3196 /* negative, lop off leading (little-endian) 0xffs */
3197 for (; significantBytes > 0 &&
3198 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
3200 if (blob->pbData[significantBytes - 1] < 0x80)
3202 padByte = 0xff;
3203 pad = TRUE;
3206 else
3208 /* positive, lop off leading (little-endian) zeroes */
3209 for (; significantBytes > 0 &&
3210 !blob->pbData[significantBytes - 1]; significantBytes--)
3212 if (significantBytes == 0)
3213 significantBytes = 1;
3214 if (blob->pbData[significantBytes - 1] > 0x7f)
3216 padByte = 0;
3217 pad = TRUE;
3221 if (pad)
3222 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3223 else
3224 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3225 bytesNeeded = 1 + lenBytes + significantBytes;
3226 if (pad)
3227 bytesNeeded++;
3228 if (!pbEncoded)
3230 *pcbEncoded = bytesNeeded;
3231 ret = TRUE;
3233 else
3235 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3236 pcbEncoded, bytesNeeded)))
3238 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3239 pbEncoded = *(BYTE **)pbEncoded;
3240 *pbEncoded++ = ASN_INTEGER;
3241 if (pad)
3243 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3244 pbEncoded += lenBytes;
3245 *pbEncoded++ = padByte;
3247 else
3249 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3250 pbEncoded += lenBytes;
3252 for (; significantBytes > 0; significantBytes--)
3253 *(pbEncoded++) = blob->pbData[significantBytes - 1];
3257 __EXCEPT_PAGE_FAULT
3259 SetLastError(STATUS_ACCESS_VIOLATION);
3260 ret = FALSE;
3262 __ENDTRY
3263 return ret;
3266 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
3267 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3268 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3270 BOOL ret;
3272 __TRY
3274 DWORD significantBytes, lenBytes, bytesNeeded;
3275 BOOL pad = FALSE;
3276 const CRYPT_INTEGER_BLOB *blob =
3277 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
3279 significantBytes = blob->cbData;
3280 if (significantBytes)
3282 /* positive, lop off leading (little-endian) zeroes */
3283 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
3284 significantBytes--)
3286 if (significantBytes == 0)
3287 significantBytes = 1;
3288 if (blob->pbData[significantBytes - 1] > 0x7f)
3289 pad = TRUE;
3291 if (pad)
3292 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3293 else
3294 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3295 bytesNeeded = 1 + lenBytes + significantBytes;
3296 if (pad)
3297 bytesNeeded++;
3298 if (!pbEncoded)
3300 *pcbEncoded = bytesNeeded;
3301 ret = TRUE;
3303 else
3305 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3306 pcbEncoded, bytesNeeded)))
3308 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3309 pbEncoded = *(BYTE **)pbEncoded;
3310 *pbEncoded++ = ASN_INTEGER;
3311 if (pad)
3313 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3314 pbEncoded += lenBytes;
3315 *pbEncoded++ = 0;
3317 else
3319 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3320 pbEncoded += lenBytes;
3322 for (; significantBytes > 0; significantBytes--)
3323 *(pbEncoded++) = blob->pbData[significantBytes - 1];
3327 __EXCEPT_PAGE_FAULT
3329 SetLastError(STATUS_ACCESS_VIOLATION);
3330 ret = FALSE;
3332 __ENDTRY
3333 return ret;
3336 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
3337 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3338 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3340 CRYPT_INTEGER_BLOB blob;
3341 BOOL ret;
3343 /* Encode as an unsigned integer, then change the tag to enumerated */
3344 blob.cbData = sizeof(DWORD);
3345 blob.pbData = (BYTE *)pvStructInfo;
3346 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
3347 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3348 if (ret && pbEncoded)
3350 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3351 pbEncoded = *(BYTE **)pbEncoded;
3352 pbEncoded[0] = ASN_ENUMERATED;
3354 return ret;
3357 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
3358 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3359 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3361 BOOL ret;
3363 __TRY
3365 SYSTEMTIME sysTime;
3366 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
3367 * temporary buffer because the output buffer is not NULL-terminated.
3369 char buf[16];
3370 static const DWORD bytesNeeded = sizeof(buf) - 1;
3372 if (!pbEncoded)
3374 *pcbEncoded = bytesNeeded;
3375 ret = TRUE;
3377 else
3379 /* Sanity check the year, this is a two-digit year format */
3380 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
3381 &sysTime);
3382 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
3384 SetLastError(CRYPT_E_BAD_ENCODE);
3385 ret = FALSE;
3387 if (ret)
3389 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3390 pbEncoded, pcbEncoded, bytesNeeded)))
3392 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3393 pbEncoded = *(BYTE **)pbEncoded;
3394 buf[0] = ASN_UTCTIME;
3395 buf[1] = bytesNeeded - 2;
3396 snprintf(buf + 2, sizeof(buf) - 2,
3397 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
3398 sysTime.wYear - 2000 : sysTime.wYear - 1900,
3399 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3400 sysTime.wMinute, sysTime.wSecond);
3401 memcpy(pbEncoded, buf, bytesNeeded);
3406 __EXCEPT_PAGE_FAULT
3408 SetLastError(STATUS_ACCESS_VIOLATION);
3409 ret = FALSE;
3411 __ENDTRY
3412 return ret;
3415 static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
3416 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3417 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3419 BOOL ret;
3421 __TRY
3423 SYSTEMTIME sysTime;
3424 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
3425 * temporary buffer because the output buffer is not NULL-terminated.
3427 char buf[18];
3428 static const DWORD bytesNeeded = sizeof(buf) - 1;
3430 if (!pbEncoded)
3432 *pcbEncoded = bytesNeeded;
3433 ret = TRUE;
3435 else
3437 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
3438 &sysTime);
3439 if (ret)
3440 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3441 pcbEncoded, bytesNeeded);
3442 if (ret)
3444 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3445 pbEncoded = *(BYTE **)pbEncoded;
3446 buf[0] = ASN_GENERALTIME;
3447 buf[1] = bytesNeeded - 2;
3448 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
3449 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3450 sysTime.wMinute, sysTime.wSecond);
3451 memcpy(pbEncoded, buf, bytesNeeded);
3455 __EXCEPT_PAGE_FAULT
3457 SetLastError(STATUS_ACCESS_VIOLATION);
3458 ret = FALSE;
3460 __ENDTRY
3461 return ret;
3464 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
3465 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3466 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3468 BOOL ret;
3470 __TRY
3472 SYSTEMTIME sysTime;
3474 /* Check the year, if it's in the UTCTime range call that encode func */
3475 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
3476 return FALSE;
3477 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
3478 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
3479 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3480 else
3481 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
3482 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
3483 pcbEncoded);
3485 __EXCEPT_PAGE_FAULT
3487 SetLastError(STATUS_ACCESS_VIOLATION);
3488 ret = FALSE;
3490 __ENDTRY
3491 return ret;
3494 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
3495 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3496 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3498 BOOL ret;
3500 __TRY
3502 DWORD bytesNeeded, dataLen, lenBytes, i;
3503 const CRYPT_SEQUENCE_OF_ANY *seq =
3504 (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3506 for (i = 0, dataLen = 0; i < seq->cValue; i++)
3507 dataLen += seq->rgValue[i].cbData;
3508 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3509 bytesNeeded = 1 + lenBytes + dataLen;
3510 if (!pbEncoded)
3512 *pcbEncoded = bytesNeeded;
3513 ret = TRUE;
3515 else
3517 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3518 pcbEncoded, bytesNeeded)))
3520 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3521 pbEncoded = *(BYTE **)pbEncoded;
3522 *pbEncoded++ = ASN_SEQUENCEOF;
3523 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
3524 pbEncoded += lenBytes;
3525 for (i = 0; i < seq->cValue; i++)
3527 memcpy(pbEncoded, seq->rgValue[i].pbData,
3528 seq->rgValue[i].cbData);
3529 pbEncoded += seq->rgValue[i].cbData;
3534 __EXCEPT_PAGE_FAULT
3536 SetLastError(STATUS_ACCESS_VIOLATION);
3537 ret = FALSE;
3539 __ENDTRY
3540 return ret;
3543 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
3544 BYTE *pbEncoded, DWORD *pcbEncoded)
3546 BOOL ret = TRUE;
3547 struct AsnEncodeSequenceItem items[3] = { { 0 } };
3548 struct AsnConstructedItem constructed = { 0 };
3549 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
3550 DWORD cItem = 0, cSwapped = 0;
3552 switch (distPoint->DistPointName.dwDistPointNameChoice)
3554 case CRL_DIST_POINT_NO_NAME:
3555 /* do nothing */
3556 break;
3557 case CRL_DIST_POINT_FULL_NAME:
3558 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3559 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
3560 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3561 constructed.tag = 0;
3562 constructed.pvStructInfo = &swapped[cSwapped];
3563 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3564 items[cItem].pvStructInfo = &constructed;
3565 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3566 cSwapped++;
3567 cItem++;
3568 break;
3569 case CRL_DIST_POINT_ISSUER_RDN_NAME:
3570 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3571 ret = FALSE;
3572 break;
3573 default:
3574 ret = FALSE;
3576 if (ret && distPoint->ReasonFlags.cbData)
3578 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3579 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
3580 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3581 items[cItem].pvStructInfo = &swapped[cSwapped];
3582 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3583 cSwapped++;
3584 cItem++;
3586 if (ret && distPoint->CRLIssuer.cAltEntry)
3588 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
3589 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
3590 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3591 items[cItem].pvStructInfo = &swapped[cSwapped];
3592 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3593 cSwapped++;
3594 cItem++;
3596 if (ret)
3597 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
3598 pbEncoded, pcbEncoded);
3599 return ret;
3602 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
3603 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3604 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3606 BOOL ret;
3608 __TRY
3610 const CRL_DIST_POINTS_INFO *info =
3611 (const CRL_DIST_POINTS_INFO *)pvStructInfo;
3613 if (!info->cDistPoint)
3615 SetLastError(E_INVALIDARG);
3616 ret = FALSE;
3618 else
3620 DWORD bytesNeeded, dataLen, lenBytes, i;
3622 ret = TRUE;
3623 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
3625 DWORD len;
3627 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
3628 &len);
3629 if (ret)
3630 dataLen += len;
3631 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
3633 /* Have to propagate index of failing character */
3634 *pcbEncoded = len;
3637 if (ret)
3639 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3640 bytesNeeded = 1 + lenBytes + dataLen;
3641 if (!pbEncoded)
3643 *pcbEncoded = bytesNeeded;
3644 ret = TRUE;
3646 else
3648 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3649 pbEncoded, pcbEncoded, bytesNeeded)))
3651 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3652 pbEncoded = *(BYTE **)pbEncoded;
3653 *pbEncoded++ = ASN_SEQUENCEOF;
3654 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
3655 pbEncoded += lenBytes;
3656 for (i = 0; ret && i < info->cDistPoint; i++)
3658 DWORD len = dataLen;
3660 ret = CRYPT_AsnEncodeDistPoint(
3661 &info->rgDistPoint[i], pbEncoded, &len);
3662 if (ret)
3664 pbEncoded += len;
3665 dataLen -= len;
3673 __EXCEPT_PAGE_FAULT
3675 SetLastError(STATUS_ACCESS_VIOLATION);
3676 ret = FALSE;
3678 __ENDTRY
3679 return ret;
3682 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3683 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3684 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3686 BOOL ret;
3688 __TRY
3690 const CERT_ENHKEY_USAGE *usage =
3691 (const CERT_ENHKEY_USAGE *)pvStructInfo;
3692 DWORD bytesNeeded = 0, lenBytes, size, i;
3694 ret = TRUE;
3695 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3697 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3698 usage->rgpszUsageIdentifier[i],
3699 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
3700 if (ret)
3701 bytesNeeded += size;
3703 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3704 bytesNeeded += 1 + lenBytes;
3705 if (ret)
3707 if (!pbEncoded)
3708 *pcbEncoded = bytesNeeded;
3709 else
3711 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3712 pbEncoded, pcbEncoded, bytesNeeded)))
3714 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3715 pbEncoded = *(BYTE **)pbEncoded;
3716 *pbEncoded++ = ASN_SEQUENCEOF;
3717 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
3718 &lenBytes);
3719 pbEncoded += lenBytes;
3720 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3722 size = bytesNeeded;
3723 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3724 usage->rgpszUsageIdentifier[i],
3725 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
3726 &size);
3727 if (ret)
3729 pbEncoded += size;
3730 bytesNeeded -= size;
3737 __EXCEPT_PAGE_FAULT
3739 SetLastError(STATUS_ACCESS_VIOLATION);
3740 ret = FALSE;
3742 __ENDTRY
3743 return ret;
3746 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
3747 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3748 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3750 BOOL ret;
3752 __TRY
3754 const CRL_ISSUING_DIST_POINT *point =
3755 (const CRL_ISSUING_DIST_POINT *)pvStructInfo;
3756 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3757 struct AsnConstructedItem constructed = { 0 };
3758 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3759 DWORD cItem = 0, cSwapped = 0;
3761 ret = TRUE;
3762 switch (point->DistPointName.dwDistPointNameChoice)
3764 case CRL_DIST_POINT_NO_NAME:
3765 /* do nothing */
3766 break;
3767 case CRL_DIST_POINT_FULL_NAME:
3768 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3769 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3770 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3771 constructed.tag = 0;
3772 constructed.pvStructInfo = &swapped[cSwapped];
3773 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3774 items[cItem].pvStructInfo = &constructed;
3775 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3776 cSwapped++;
3777 cItem++;
3778 break;
3779 default:
3780 SetLastError(E_INVALIDARG);
3781 ret = FALSE;
3783 if (ret && point->fOnlyContainsUserCerts)
3785 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3786 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3787 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3788 items[cItem].pvStructInfo = &swapped[cSwapped];
3789 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3790 cSwapped++;
3791 cItem++;
3793 if (ret && point->fOnlyContainsCACerts)
3795 swapped[cSwapped].tag = ASN_CONTEXT | 2;
3796 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3797 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3798 items[cItem].pvStructInfo = &swapped[cSwapped];
3799 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3800 cSwapped++;
3801 cItem++;
3803 if (ret && point->OnlySomeReasonFlags.cbData)
3805 swapped[cSwapped].tag = ASN_CONTEXT | 3;
3806 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3807 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3808 items[cItem].pvStructInfo = &swapped[cSwapped];
3809 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3810 cSwapped++;
3811 cItem++;
3813 if (ret && point->fIndirectCRL)
3815 swapped[cSwapped].tag = ASN_CONTEXT | 4;
3816 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
3817 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3818 items[cItem].pvStructInfo = &swapped[cSwapped];
3819 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3820 cSwapped++;
3821 cItem++;
3823 if (ret)
3824 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3825 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3827 __EXCEPT_PAGE_FAULT
3829 SetLastError(STATUS_ACCESS_VIOLATION);
3830 ret = FALSE;
3832 __ENDTRY
3833 return ret;
3836 static BOOL WINAPI CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType,
3837 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3838 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3840 BOOL ret;
3841 const CERT_GENERAL_SUBTREE *subtree =
3842 (const CERT_GENERAL_SUBTREE *)pvStructInfo;
3843 struct AsnEncodeSequenceItem items[3] = {
3844 { &subtree->Base, CRYPT_AsnEncodeAltNameEntry, 0 },
3845 { 0 }
3847 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3848 DWORD cItem = 1, cSwapped = 0;
3850 if (subtree->dwMinimum)
3852 swapped[cSwapped].tag = ASN_CONTEXT | 0;
3853 swapped[cSwapped].pvStructInfo = &subtree->dwMinimum;
3854 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3855 items[cItem].pvStructInfo = &swapped[cSwapped];
3856 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3857 cSwapped++;
3858 cItem++;
3860 if (subtree->fMaximum)
3862 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3863 swapped[cSwapped].pvStructInfo = &subtree->dwMaximum;
3864 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3865 items[cItem].pvStructInfo = &swapped[cSwapped];
3866 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3867 cSwapped++;
3868 cItem++;
3870 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags,
3871 pEncodePara, pbEncoded, pcbEncoded);
3872 return ret;
3875 static BOOL WINAPI CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType,
3876 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3877 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3879 BOOL ret = FALSE;
3880 CRYPT_BLOB_ARRAY permitted = { 0, NULL }, excluded = { 0, NULL };
3882 TRACE("%p\n", pvStructInfo);
3884 __TRY
3886 const CERT_NAME_CONSTRAINTS_INFO *constraints =
3887 (const CERT_NAME_CONSTRAINTS_INFO *)pvStructInfo;
3888 struct AsnEncodeSequenceItem items[2] = { { 0 } };
3889 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3890 DWORD i, cItem = 0, cSwapped = 0;
3892 ret = TRUE;
3893 if (constraints->cPermittedSubtree)
3895 permitted.rgBlob = CryptMemAlloc(
3896 constraints->cPermittedSubtree * sizeof(CRYPT_DER_BLOB));
3897 if (permitted.rgBlob)
3899 permitted.cBlob = constraints->cPermittedSubtree;
3900 memset(permitted.rgBlob, 0,
3901 permitted.cBlob * sizeof(CRYPT_DER_BLOB));
3902 for (i = 0; ret && i < permitted.cBlob; i++)
3903 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3904 NULL, &constraints->rgPermittedSubtree[i],
3905 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3906 (BYTE *)&permitted.rgBlob[i].pbData,
3907 &permitted.rgBlob[i].cbData);
3908 if (ret)
3910 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3911 swapped[cSwapped].pvStructInfo = &permitted;
3912 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3913 items[cItem].pvStructInfo = &swapped[cSwapped];
3914 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3915 cSwapped++;
3916 cItem++;
3919 else
3920 ret = FALSE;
3922 if (constraints->cExcludedSubtree)
3924 excluded.rgBlob = CryptMemAlloc(
3925 constraints->cExcludedSubtree * sizeof(CRYPT_DER_BLOB));
3926 if (excluded.rgBlob)
3928 excluded.cBlob = constraints->cExcludedSubtree;
3929 memset(excluded.rgBlob, 0,
3930 excluded.cBlob * sizeof(CRYPT_DER_BLOB));
3931 for (i = 0; ret && i < excluded.cBlob; i++)
3932 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3933 NULL, &constraints->rgExcludedSubtree[i],
3934 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3935 (BYTE *)&excluded.rgBlob[i].pbData,
3936 &excluded.rgBlob[i].cbData);
3937 if (ret)
3939 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
3940 swapped[cSwapped].pvStructInfo = &excluded;
3941 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3942 items[cItem].pvStructInfo = &swapped[cSwapped];
3943 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3944 cSwapped++;
3945 cItem++;
3948 else
3949 ret = FALSE;
3951 if (ret)
3952 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3953 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3954 for (i = 0; i < permitted.cBlob; i++)
3955 LocalFree(permitted.rgBlob[i].pbData);
3956 for (i = 0; i < excluded.cBlob; i++)
3957 LocalFree(excluded.rgBlob[i].pbData);
3959 __EXCEPT_PAGE_FAULT
3961 SetLastError(STATUS_ACCESS_VIOLATION);
3963 __ENDTRY
3964 CryptMemFree(permitted.rgBlob);
3965 CryptMemFree(excluded.rgBlob);
3966 TRACE("returning %d\n", ret);
3967 return ret;
3970 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
3971 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3972 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3973 DWORD *pcbEncoded)
3975 BOOL ret;
3976 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3977 (const CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3978 struct AsnEncodeSequenceItem items[] = {
3979 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
3980 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
3983 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3984 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3985 pcbEncoded);
3986 return ret;
3989 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
3990 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3991 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3993 BOOL ret = FALSE;
3995 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
3997 SetLastError(E_INVALIDARG);
3998 return FALSE;
4001 __TRY
4003 const CMSG_SIGNER_INFO *info = (const CMSG_SIGNER_INFO *)pvStructInfo;
4005 if (!info->Issuer.cbData)
4006 SetLastError(E_INVALIDARG);
4007 else
4009 struct AsnEncodeSequenceItem items[7] = {
4010 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4011 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
4012 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
4013 0 },
4015 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4016 DWORD cItem = 3, cSwapped = 0;
4018 if (info->AuthAttrs.cAttr)
4020 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4021 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
4022 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4023 items[cItem].pvStructInfo = &swapped[cSwapped];
4024 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4025 cSwapped++;
4026 cItem++;
4028 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
4029 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4030 cItem++;
4031 items[cItem].pvStructInfo = &info->EncryptedHash;
4032 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
4033 cItem++;
4034 if (info->UnauthAttrs.cAttr)
4036 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4037 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
4038 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4039 items[cItem].pvStructInfo = &swapped[cSwapped];
4040 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4041 cSwapped++;
4042 cItem++;
4044 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4045 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4048 __EXCEPT_PAGE_FAULT
4050 SetLastError(STATUS_ACCESS_VIOLATION);
4052 __ENDTRY
4053 return ret;
4056 static BOOL WINAPI CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType,
4057 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4058 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4060 BOOL ret = FALSE;
4062 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
4064 SetLastError(E_INVALIDARG);
4065 return FALSE;
4068 __TRY
4070 const CMSG_CMS_SIGNER_INFO *info = (const CMSG_CMS_SIGNER_INFO *)pvStructInfo;
4072 if (info->SignerId.dwIdChoice != CERT_ID_ISSUER_SERIAL_NUMBER &&
4073 info->SignerId.dwIdChoice != CERT_ID_KEY_IDENTIFIER)
4074 SetLastError(E_INVALIDARG);
4075 else if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER &&
4076 !info->SignerId.u.IssuerSerialNumber.Issuer.cbData)
4077 SetLastError(E_INVALIDARG);
4078 else
4080 struct AsnEncodeSequenceItem items[7] = {
4081 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4083 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
4084 DWORD cItem = 1, cSwapped = 0;
4086 if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
4088 items[cItem].pvStructInfo =
4089 &info->SignerId.u.IssuerSerialNumber.Issuer;
4090 items[cItem].encodeFunc =
4091 CRYPT_AsnEncodeIssuerSerialNumber;
4092 cItem++;
4094 else
4096 swapped[cSwapped].tag = ASN_CONTEXT | 0;
4097 swapped[cSwapped].pvStructInfo = &info->SignerId.u.KeyId;
4098 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
4099 items[cItem].pvStructInfo = &swapped[cSwapped];
4100 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4101 cSwapped++;
4102 cItem++;
4104 items[cItem].pvStructInfo = &info->HashAlgorithm;
4105 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4106 cItem++;
4107 if (info->AuthAttrs.cAttr)
4109 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4110 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
4111 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4112 items[cItem].pvStructInfo = &swapped[cSwapped];
4113 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4114 cSwapped++;
4115 cItem++;
4117 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
4118 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4119 cItem++;
4120 items[cItem].pvStructInfo = &info->EncryptedHash;
4121 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
4122 cItem++;
4123 if (info->UnauthAttrs.cAttr)
4125 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4126 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
4127 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4128 items[cItem].pvStructInfo = &swapped[cSwapped];
4129 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4130 cSwapped++;
4131 cItem++;
4133 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4134 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4137 __EXCEPT_PAGE_FAULT
4139 SetLastError(STATUS_ACCESS_VIOLATION);
4141 __ENDTRY
4142 return ret;
4145 BOOL CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
4146 DWORD *pcbData)
4148 struct AsnEncodeSequenceItem items[7] = {
4149 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
4151 struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 };
4152 struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 };
4153 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4154 DWORD cItem = 1, cSwapped = 0;
4155 BOOL ret = TRUE;
4157 if (signedInfo->cSignerInfo)
4159 digestAlgorithmsSet.cItems = signedInfo->cSignerInfo;
4160 digestAlgorithmsSet.items = signedInfo->rgSignerInfo;
4161 digestAlgorithmsSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
4162 digestAlgorithmsSet.itemOffset =
4163 offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm);
4164 digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4165 items[cItem].pvStructInfo = &digestAlgorithmsSet;
4166 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4167 cItem++;
4169 items[cItem].pvStructInfo = &signedInfo->content;
4170 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal;
4171 cItem++;
4172 if (signedInfo->cCertEncoded)
4174 certSet.cItems = signedInfo->cCertEncoded;
4175 certSet.items = signedInfo->rgCertEncoded;
4176 certSet.itemSize = sizeof(CERT_BLOB);
4177 certSet.itemOffset = 0;
4178 certSet.encode = CRYPT_CopyEncodedBlob;
4179 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0;
4180 swapped[cSwapped].pvStructInfo = &certSet;
4181 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4182 items[cItem].pvStructInfo = &swapped[cSwapped];
4183 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4184 cSwapped++;
4185 cItem++;
4187 if (signedInfo->cCrlEncoded)
4189 crlSet.cItems = signedInfo->cCrlEncoded;
4190 crlSet.items = signedInfo->rgCrlEncoded;
4191 crlSet.itemSize = sizeof(CRL_BLOB);
4192 crlSet.itemOffset = 0;
4193 crlSet.encode = CRYPT_CopyEncodedBlob;
4194 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
4195 swapped[cSwapped].pvStructInfo = &crlSet;
4196 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4197 items[cItem].pvStructInfo = &swapped[cSwapped];
4198 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4199 cSwapped++;
4200 cItem++;
4202 if (ret && signedInfo->cSignerInfo)
4204 signerSet.cItems = signedInfo->cSignerInfo;
4205 signerSet.items = signedInfo->rgSignerInfo;
4206 signerSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
4207 signerSet.itemOffset = 0;
4208 signerSet.encode = CRYPT_AsnEncodeCMSSignerInfo;
4209 items[cItem].pvStructInfo = &signerSet;
4210 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4211 cItem++;
4213 if (ret)
4214 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
4215 items, cItem, 0, NULL, pvData, pcbData);
4217 return ret;
4220 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
4221 LPCSTR lpszStructType)
4223 CryptEncodeObjectExFunc encodeFunc = NULL;
4225 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4226 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4228 SetLastError(ERROR_FILE_NOT_FOUND);
4229 return NULL;
4232 if (!HIWORD(lpszStructType))
4234 switch (LOWORD(lpszStructType))
4236 case LOWORD(X509_CERT):
4237 encodeFunc = CRYPT_AsnEncodeCert;
4238 break;
4239 case LOWORD(X509_CERT_TO_BE_SIGNED):
4240 encodeFunc = CRYPT_AsnEncodeCertInfo;
4241 break;
4242 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
4243 encodeFunc = CRYPT_AsnEncodeCRLInfo;
4244 break;
4245 case LOWORD(X509_EXTENSIONS):
4246 encodeFunc = CRYPT_AsnEncodeExtensions;
4247 break;
4248 case LOWORD(X509_NAME_VALUE):
4249 encodeFunc = CRYPT_AsnEncodeNameValue;
4250 break;
4251 case LOWORD(X509_NAME):
4252 encodeFunc = CRYPT_AsnEncodeName;
4253 break;
4254 case LOWORD(X509_PUBLIC_KEY_INFO):
4255 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
4256 break;
4257 case LOWORD(X509_AUTHORITY_KEY_ID):
4258 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
4259 break;
4260 case LOWORD(X509_ALTERNATE_NAME):
4261 encodeFunc = CRYPT_AsnEncodeAltName;
4262 break;
4263 case LOWORD(X509_BASIC_CONSTRAINTS):
4264 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
4265 break;
4266 case LOWORD(X509_BASIC_CONSTRAINTS2):
4267 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
4268 break;
4269 case LOWORD(X509_CERT_POLICIES):
4270 encodeFunc = CRYPT_AsnEncodeCertPolicies;
4271 break;
4272 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
4273 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
4274 break;
4275 case LOWORD(X509_UNICODE_NAME):
4276 encodeFunc = CRYPT_AsnEncodeUnicodeName;
4277 break;
4278 case LOWORD(PKCS_CONTENT_INFO):
4279 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
4280 break;
4281 case LOWORD(PKCS_ATTRIBUTE):
4282 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
4283 break;
4284 case LOWORD(X509_UNICODE_NAME_VALUE):
4285 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
4286 break;
4287 case LOWORD(X509_OCTET_STRING):
4288 encodeFunc = CRYPT_AsnEncodeOctets;
4289 break;
4290 case LOWORD(X509_BITS):
4291 case LOWORD(X509_KEY_USAGE):
4292 encodeFunc = CRYPT_AsnEncodeBits;
4293 break;
4294 case LOWORD(X509_INTEGER):
4295 encodeFunc = CRYPT_AsnEncodeInt;
4296 break;
4297 case LOWORD(X509_MULTI_BYTE_INTEGER):
4298 encodeFunc = CRYPT_AsnEncodeInteger;
4299 break;
4300 case LOWORD(X509_MULTI_BYTE_UINT):
4301 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
4302 break;
4303 case LOWORD(X509_ENUMERATED):
4304 encodeFunc = CRYPT_AsnEncodeEnumerated;
4305 break;
4306 case LOWORD(X509_CHOICE_OF_TIME):
4307 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
4308 break;
4309 case LOWORD(X509_AUTHORITY_KEY_ID2):
4310 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
4311 break;
4312 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
4313 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
4314 break;
4315 case LOWORD(X509_SEQUENCE_OF_ANY):
4316 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
4317 break;
4318 case LOWORD(PKCS_UTC_TIME):
4319 encodeFunc = CRYPT_AsnEncodeUtcTime;
4320 break;
4321 case LOWORD(X509_CRL_DIST_POINTS):
4322 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
4323 break;
4324 case LOWORD(X509_ENHANCED_KEY_USAGE):
4325 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
4326 break;
4327 case LOWORD(PKCS_CTL):
4328 encodeFunc = CRYPT_AsnEncodeCTL;
4329 break;
4330 case LOWORD(PKCS_SMIME_CAPABILITIES):
4331 encodeFunc = CRYPT_AsnEncodeSMIMECapabilities;
4332 break;
4333 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
4334 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
4335 break;
4336 case LOWORD(PKCS_ATTRIBUTES):
4337 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4338 break;
4339 case LOWORD(X509_ISSUING_DIST_POINT):
4340 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
4341 break;
4342 case LOWORD(X509_NAME_CONSTRAINTS):
4343 encodeFunc = CRYPT_AsnEncodeNameConstraints;
4344 break;
4345 case LOWORD(PKCS7_SIGNER_INFO):
4346 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
4347 break;
4348 case LOWORD(CMS_SIGNER_INFO):
4349 encodeFunc = CRYPT_AsnEncodeCMSSignerInfo;
4350 break;
4353 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4354 encodeFunc = CRYPT_AsnEncodeExtensions;
4355 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4356 encodeFunc = CRYPT_AsnEncodeUtcTime;
4357 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
4358 encodeFunc = CRYPT_AsnEncodeUtcTime;
4359 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4360 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
4361 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4362 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
4363 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4364 encodeFunc = CRYPT_AsnEncodeEnumerated;
4365 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4366 encodeFunc = CRYPT_AsnEncodeBits;
4367 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4368 encodeFunc = CRYPT_AsnEncodeOctets;
4369 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4370 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
4371 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4372 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
4373 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4374 encodeFunc = CRYPT_AsnEncodeAltName;
4375 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4376 encodeFunc = CRYPT_AsnEncodeAltName;
4377 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4378 encodeFunc = CRYPT_AsnEncodeAltName;
4379 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4380 encodeFunc = CRYPT_AsnEncodeAltName;
4381 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4382 encodeFunc = CRYPT_AsnEncodeAltName;
4383 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4384 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
4385 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
4386 encodeFunc = CRYPT_AsnEncodeCertPolicies;
4387 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4388 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
4389 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4390 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
4391 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
4392 encodeFunc = CRYPT_AsnEncodeNameConstraints;
4393 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
4394 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
4395 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
4396 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
4397 else if (!strcmp(lpszStructType, szOID_CTL))
4398 encodeFunc = CRYPT_AsnEncodeCTL;
4399 return encodeFunc;
4402 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType,
4403 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4405 static HCRYPTOIDFUNCSET set = NULL;
4406 CryptEncodeObjectFunc encodeFunc = NULL;
4408 if (!set)
4409 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
4410 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4411 (void **)&encodeFunc, hFunc);
4412 return encodeFunc;
4415 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType,
4416 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4418 static HCRYPTOIDFUNCSET set = NULL;
4419 CryptEncodeObjectExFunc encodeFunc = NULL;
4421 if (!set)
4422 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
4423 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4424 (void **)&encodeFunc, hFunc);
4425 return encodeFunc;
4428 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4429 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
4431 BOOL ret = FALSE;
4432 HCRYPTOIDFUNCADDR hFunc = NULL;
4433 CryptEncodeObjectFunc pCryptEncodeObject = NULL;
4434 CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL;
4436 TRACE_(crypt)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
4437 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
4438 pcbEncoded);
4440 if (!pbEncoded && !pcbEncoded)
4442 SetLastError(ERROR_INVALID_PARAMETER);
4443 return FALSE;
4446 if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType,
4447 lpszStructType)))
4449 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4450 debugstr_a(lpszStructType));
4451 pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType,
4452 lpszStructType, &hFunc);
4453 if (!pCryptEncodeObject)
4454 pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType,
4455 lpszStructType, &hFunc);
4457 if (pCryptEncodeObject)
4458 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4459 pvStructInfo, pbEncoded, pcbEncoded);
4460 else if (pCryptEncodeObjectEx)
4461 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
4462 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
4463 if (hFunc)
4464 CryptFreeOIDFunctionAddress(hFunc, 0);
4465 TRACE_(crypt)("returning %d\n", ret);
4466 return ret;
4469 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4470 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
4471 void *pvEncoded, DWORD *pcbEncoded)
4473 BOOL ret = FALSE;
4474 HCRYPTOIDFUNCADDR hFunc = NULL;
4475 CryptEncodeObjectExFunc encodeFunc = NULL;
4477 TRACE_(crypt)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
4478 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
4479 pvEncoded, pcbEncoded);
4481 if (!pvEncoded && !pcbEncoded)
4483 SetLastError(ERROR_INVALID_PARAMETER);
4484 return FALSE;
4487 SetLastError(NOERROR);
4488 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
4489 *(BYTE **)pvEncoded = NULL;
4490 encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType);
4491 if (!encodeFunc)
4493 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4494 debugstr_a(lpszStructType));
4495 encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType,
4496 &hFunc);
4498 if (encodeFunc)
4499 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
4500 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
4501 else
4503 CryptEncodeObjectFunc pCryptEncodeObject =
4504 CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4506 if (pCryptEncodeObject)
4508 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
4510 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4511 pvStructInfo, NULL, pcbEncoded);
4512 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
4513 pvEncoded, pcbEncoded, *pcbEncoded)))
4514 ret = pCryptEncodeObject(dwCertEncodingType,
4515 lpszStructType, pvStructInfo, *(BYTE **)pvEncoded,
4516 pcbEncoded);
4518 else
4519 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4520 pvStructInfo, pvEncoded, pcbEncoded);
4523 if (hFunc)
4524 CryptFreeOIDFunctionAddress(hFunc, 0);
4525 TRACE_(crypt)("returning %d\n", ret);
4526 return ret;
4529 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
4530 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4532 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
4533 NULL, 0, NULL, pInfo, pcbInfo);
4536 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
4537 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
4538 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4540 BOOL ret;
4541 HCRYPTKEY key;
4542 static CHAR oid[] = szOID_RSA_RSA;
4544 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
4545 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
4546 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
4548 if (!pszPublicKeyObjId)
4549 pszPublicKeyObjId = oid;
4550 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
4552 DWORD keySize = 0;
4554 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
4555 if (ret)
4557 LPBYTE pubKey = CryptMemAlloc(keySize);
4559 if (pubKey)
4561 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
4562 &keySize);
4563 if (ret)
4565 DWORD encodedLen = 0;
4567 ret = CryptEncodeObject(dwCertEncodingType,
4568 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
4569 if (ret)
4571 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
4572 strlen(pszPublicKeyObjId) + 1 + encodedLen;
4574 if (!pInfo)
4575 *pcbInfo = sizeNeeded;
4576 else if (*pcbInfo < sizeNeeded)
4578 SetLastError(ERROR_MORE_DATA);
4579 *pcbInfo = sizeNeeded;
4580 ret = FALSE;
4582 else
4584 pInfo->Algorithm.pszObjId = (char *)pInfo +
4585 sizeof(CERT_PUBLIC_KEY_INFO);
4586 lstrcpyA(pInfo->Algorithm.pszObjId,
4587 pszPublicKeyObjId);
4588 pInfo->Algorithm.Parameters.cbData = 0;
4589 pInfo->Algorithm.Parameters.pbData = NULL;
4590 pInfo->PublicKey.pbData =
4591 (BYTE *)pInfo->Algorithm.pszObjId
4592 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
4593 pInfo->PublicKey.cbData = encodedLen;
4594 pInfo->PublicKey.cUnusedBits = 0;
4595 ret = CryptEncodeObject(dwCertEncodingType,
4596 RSA_CSP_PUBLICKEYBLOB, pubKey,
4597 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
4601 CryptMemFree(pubKey);
4603 else
4604 ret = FALSE;
4606 CryptDestroyKey(key);
4608 return ret;
4611 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
4612 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
4613 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
4615 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
4616 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
4617 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4619 static HCRYPTOIDFUNCSET set = NULL;
4620 BOOL ret;
4621 ExportPublicKeyInfoExFunc exportFunc = NULL;
4622 HCRYPTOIDFUNCADDR hFunc = NULL;
4624 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
4625 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
4626 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
4628 if (!hCryptProv)
4630 SetLastError(ERROR_INVALID_PARAMETER);
4631 return FALSE;
4634 if (pszPublicKeyObjId)
4636 if (!set)
4637 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
4639 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
4640 0, (void **)&exportFunc, &hFunc);
4642 if (!exportFunc)
4643 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
4644 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
4645 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
4646 if (hFunc)
4647 CryptFreeOIDFunctionAddress(hFunc, 0);
4648 return ret;
4651 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
4652 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
4654 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
4655 0, 0, NULL, phKey);
4658 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
4659 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4660 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
4662 BOOL ret;
4663 DWORD pubKeySize = 0;
4665 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
4666 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
4668 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
4669 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
4670 if (ret)
4672 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
4674 if (pubKey)
4676 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
4677 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
4678 &pubKeySize);
4679 if (ret)
4681 if(aiKeyAlg)
4682 ((BLOBHEADER*)pubKey)->aiKeyAlg = aiKeyAlg;
4683 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
4684 phKey);
4686 CryptMemFree(pubKey);
4688 else
4689 ret = FALSE;
4691 return ret;
4694 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
4695 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4696 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
4698 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
4699 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4700 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
4702 static HCRYPTOIDFUNCSET set = NULL;
4703 BOOL ret;
4704 ImportPublicKeyInfoExFunc importFunc = NULL;
4705 HCRYPTOIDFUNCADDR hFunc = NULL;
4707 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
4708 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
4710 if (!set)
4711 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
4712 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
4713 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
4714 if (!importFunc)
4715 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
4716 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
4717 pvAuxInfo, phKey);
4718 if (hFunc)
4719 CryptFreeOIDFunctionAddress(hFunc, 0);
4720 return ret;