user32: Fix SPI_SETMOUSESPEED handling, the parameter is not a pointer.
[wine/wine64.git] / dlls / crypt32 / encode.c
blob2440d1696f14652b8ebf943f5b293c5f34630c60
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 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 if (*ptr == '.')
809 ptr++;
810 firstPos++;
812 while (ret && *ptr)
814 int pos;
816 /* note I assume each component is at most 32-bits long in base 2 */
817 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
819 if (val1 >= 0x10000000)
820 bytesNeeded += 5;
821 else if (val1 >= 0x200000)
822 bytesNeeded += 4;
823 else if (val1 >= 0x4000)
824 bytesNeeded += 3;
825 else if (val1 >= 0x80)
826 bytesNeeded += 2;
827 else
828 bytesNeeded += 1;
829 ptr += pos;
830 if (*ptr == '.')
831 ptr++;
833 else
835 SetLastError(CRYPT_E_ASN1_ERROR);
836 return FALSE;
839 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
841 else
842 lenBytes = 1;
843 bytesNeeded += 1 + lenBytes;
844 if (pbEncoded)
846 if (*pcbEncoded < bytesNeeded)
848 SetLastError(ERROR_MORE_DATA);
849 ret = FALSE;
851 else
853 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
854 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
855 pbEncoded += lenBytes;
856 if (pszObjId)
858 const char *ptr;
859 int val, pos;
861 *pbEncoded++ = firstByte;
862 ptr = pszObjId + firstPos;
863 while (ret && *ptr)
865 sscanf(ptr, "%d%n", &val, &pos);
867 unsigned char outBytes[5];
868 int numBytes, i;
870 if (val >= 0x10000000)
871 numBytes = 5;
872 else if (val >= 0x200000)
873 numBytes = 4;
874 else if (val >= 0x4000)
875 numBytes = 3;
876 else if (val >= 0x80)
877 numBytes = 2;
878 else
879 numBytes = 1;
880 for (i = numBytes; i > 0; i--)
882 outBytes[i - 1] = val & 0x7f;
883 val >>= 7;
885 for (i = 0; i < numBytes - 1; i++)
886 *pbEncoded++ = outBytes[i] | 0x80;
887 *pbEncoded++ = outBytes[i];
888 ptr += pos;
889 if (*ptr == '.')
890 ptr++;
896 *pcbEncoded = bytesNeeded;
897 return ret;
900 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
901 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
902 DWORD *pcbEncoded)
904 BOOL ret = TRUE;
905 LPCSTR str = (LPCSTR)value->Value.pbData;
906 DWORD bytesNeeded, lenBytes, encodedLen;
908 encodedLen = value->Value.cbData ? value->Value.cbData : strlen(str);
909 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
910 bytesNeeded = 1 + lenBytes + encodedLen;
911 if (!pbEncoded)
912 *pcbEncoded = bytesNeeded;
913 else
915 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
916 pbEncoded, pcbEncoded, bytesNeeded)))
918 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
919 pbEncoded = *(BYTE **)pbEncoded;
920 *pbEncoded++ = tag;
921 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
922 pbEncoded += lenBytes;
923 memcpy(pbEncoded, str, encodedLen);
926 return ret;
929 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
930 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
931 DWORD *pcbEncoded)
933 BOOL ret = TRUE;
934 LPCWSTR str = (LPCWSTR)value->Value.pbData;
935 DWORD bytesNeeded, lenBytes, strLen;
937 if (value->Value.cbData)
938 strLen = value->Value.cbData / sizeof(WCHAR);
939 else if (value->Value.pbData)
940 strLen = lstrlenW(str);
941 else
942 strLen = 0;
943 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
944 bytesNeeded = 1 + lenBytes + strLen * 2;
945 if (!pbEncoded)
946 *pcbEncoded = bytesNeeded;
947 else
949 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
950 pbEncoded, pcbEncoded, bytesNeeded)))
952 DWORD i;
954 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
955 pbEncoded = *(BYTE **)pbEncoded;
956 *pbEncoded++ = ASN_BMPSTRING;
957 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
958 pbEncoded += lenBytes;
959 for (i = 0; i < strLen; i++)
961 *pbEncoded++ = (str[i] & 0xff00) >> 8;
962 *pbEncoded++ = str[i] & 0x00ff;
966 return ret;
969 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
970 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
971 DWORD *pcbEncoded)
973 BOOL ret = TRUE;
974 LPCWSTR str = (LPCWSTR)value->Value.pbData;
975 DWORD bytesNeeded, lenBytes, encodedLen, strLen;
977 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
978 strlenW(str);
979 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
980 NULL);
981 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
982 bytesNeeded = 1 + lenBytes + encodedLen;
983 if (!pbEncoded)
984 *pcbEncoded = bytesNeeded;
985 else
987 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
988 pbEncoded, pcbEncoded, bytesNeeded)))
990 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
991 pbEncoded = *(BYTE **)pbEncoded;
992 *pbEncoded++ = ASN_UTF8STRING;
993 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
994 pbEncoded += lenBytes;
995 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
996 bytesNeeded - lenBytes - 1, NULL, NULL);
999 return ret;
1002 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
1003 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1004 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1006 BOOL ret = TRUE;
1008 __TRY
1010 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1012 switch (value->dwValueType)
1014 case CERT_RDN_ANY_TYPE:
1015 /* explicitly disallowed */
1016 SetLastError(E_INVALIDARG);
1017 ret = FALSE;
1018 break;
1019 case CERT_RDN_ENCODED_BLOB:
1020 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
1021 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1022 break;
1023 case CERT_RDN_OCTET_STRING:
1024 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1025 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1026 break;
1027 case CERT_RDN_NUMERIC_STRING:
1028 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1029 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1030 break;
1031 case CERT_RDN_PRINTABLE_STRING:
1032 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1033 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1034 break;
1035 case CERT_RDN_TELETEX_STRING:
1036 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1037 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1038 break;
1039 case CERT_RDN_VIDEOTEX_STRING:
1040 ret = CRYPT_AsnEncodeStringCoerce(value,
1041 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1042 break;
1043 case CERT_RDN_IA5_STRING:
1044 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1045 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1046 break;
1047 case CERT_RDN_GRAPHIC_STRING:
1048 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1049 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1050 break;
1051 case CERT_RDN_VISIBLE_STRING:
1052 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1053 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1054 break;
1055 case CERT_RDN_GENERAL_STRING:
1056 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1057 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1058 break;
1059 case CERT_RDN_UNIVERSAL_STRING:
1060 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1061 SetLastError(CRYPT_E_ASN1_CHOICE);
1062 ret = FALSE;
1063 break;
1064 case CERT_RDN_BMP_STRING:
1065 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1066 pbEncoded, pcbEncoded);
1067 break;
1068 case CERT_RDN_UTF8_STRING:
1069 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1070 pbEncoded, pcbEncoded);
1071 break;
1072 default:
1073 SetLastError(CRYPT_E_ASN1_CHOICE);
1074 ret = FALSE;
1077 __EXCEPT_PAGE_FAULT
1079 SetLastError(STATUS_ACCESS_VIOLATION);
1080 ret = FALSE;
1082 __ENDTRY
1083 return ret;
1086 static BOOL CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1087 CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1088 BYTE *pbEncoded, DWORD *pcbEncoded)
1090 DWORD bytesNeeded = 0, lenBytes, size;
1091 BOOL ret;
1093 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1094 0, NULL, NULL, &size);
1095 if (ret)
1097 bytesNeeded += size;
1098 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1099 * with dwValueType, so "cast" it to get its encoded size
1101 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1102 (CERT_NAME_VALUE *)&attr->dwValueType, 0, NULL, NULL, &size);
1103 if (ret)
1105 bytesNeeded += size;
1106 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1107 bytesNeeded += 1 + lenBytes;
1108 if (pbEncoded)
1110 if (*pcbEncoded < bytesNeeded)
1112 SetLastError(ERROR_MORE_DATA);
1113 ret = FALSE;
1115 else
1117 *pbEncoded++ = ASN_SEQUENCE;
1118 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1119 &lenBytes);
1120 pbEncoded += lenBytes;
1121 size = bytesNeeded - 1 - lenBytes;
1122 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1123 attr->pszObjId, 0, NULL, pbEncoded, &size);
1124 if (ret)
1126 pbEncoded += size;
1127 size = bytesNeeded - 1 - lenBytes - size;
1128 ret = nameValueEncodeFunc(dwCertEncodingType,
1129 NULL, (CERT_NAME_VALUE *)&attr->dwValueType,
1130 0, NULL, pbEncoded, &size);
1131 if (!ret)
1132 *pcbEncoded = size;
1136 if (ret)
1137 *pcbEncoded = bytesNeeded;
1139 else
1141 /* Have to propagate index of failing character */
1142 *pcbEncoded = size;
1145 return ret;
1148 static int BLOBComp(const void *l, const void *r)
1150 const CRYPT_DER_BLOB *a = (const CRYPT_DER_BLOB *)l, *b = (const CRYPT_DER_BLOB *)r;
1151 int ret;
1153 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1154 ret = a->cbData - b->cbData;
1155 return ret;
1158 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1160 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1161 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1162 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1164 const CRYPT_BLOB_ARRAY *set = (const CRYPT_BLOB_ARRAY *)pvStructInfo;
1165 DWORD bytesNeeded = 0, lenBytes, i;
1166 BOOL ret;
1168 for (i = 0; i < set->cBlob; i++)
1169 bytesNeeded += set->rgBlob[i].cbData;
1170 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1171 bytesNeeded += 1 + lenBytes;
1172 if (!pbEncoded)
1174 *pcbEncoded = bytesNeeded;
1175 ret = TRUE;
1177 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1178 pbEncoded, pcbEncoded, bytesNeeded)))
1180 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1181 pbEncoded = *(BYTE **)pbEncoded;
1182 qsort(set->rgBlob, set->cBlob, sizeof(CRYPT_DER_BLOB), BLOBComp);
1183 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1184 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1185 pbEncoded += lenBytes;
1186 for (i = 0; ret && i < set->cBlob; i++)
1188 memcpy(pbEncoded, set->rgBlob[i].pbData, set->rgBlob[i].cbData);
1189 pbEncoded += set->rgBlob[i].cbData;
1192 return ret;
1195 struct DERSetDescriptor
1197 DWORD cItems;
1198 const void *items;
1199 size_t itemSize;
1200 size_t itemOffset;
1201 CryptEncodeObjectExFunc encode;
1204 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,
1205 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1206 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1208 const struct DERSetDescriptor *desc =
1209 (const struct DERSetDescriptor *)pvStructInfo;
1210 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1211 BOOL ret = TRUE;
1212 DWORD i;
1214 if (desc->cItems)
1216 setOf.rgBlob = CryptMemAlloc(desc->cItems * sizeof(CRYPT_DER_BLOB));
1217 if (!setOf.rgBlob)
1218 ret = FALSE;
1219 else
1221 setOf.cBlob = desc->cItems;
1222 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1225 for (i = 0; ret && i < setOf.cBlob; i++)
1227 ret = desc->encode(dwCertEncodingType, lpszStructType,
1228 (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
1229 0, NULL, NULL, &setOf.rgBlob[i].cbData);
1230 if (ret)
1232 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1233 if (!setOf.rgBlob[i].pbData)
1234 ret = FALSE;
1235 else
1236 ret = desc->encode(dwCertEncodingType, lpszStructType,
1237 (const BYTE *)desc->items + i * desc->itemSize +
1238 desc->itemOffset, 0, NULL, setOf.rgBlob[i].pbData,
1239 &setOf.rgBlob[i].cbData);
1241 /* Some functions propagate their errors through the size */
1242 if (!ret)
1243 *pcbEncoded = setOf.rgBlob[i].cbData;
1245 if (ret)
1247 DWORD bytesNeeded = 0, lenBytes;
1249 for (i = 0; i < setOf.cBlob; i++)
1250 bytesNeeded += setOf.rgBlob[i].cbData;
1251 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1252 bytesNeeded += 1 + lenBytes;
1253 if (!pbEncoded)
1254 *pcbEncoded = bytesNeeded;
1255 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1256 pbEncoded, pcbEncoded, bytesNeeded)))
1258 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1259 pbEncoded = *(BYTE **)pbEncoded;
1260 qsort(setOf.rgBlob, setOf.cBlob, sizeof(CRYPT_DER_BLOB),
1261 BLOBComp);
1262 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1263 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1264 pbEncoded += lenBytes;
1265 for (i = 0; i < setOf.cBlob; i++)
1267 memcpy(pbEncoded, setOf.rgBlob[i].pbData,
1268 setOf.rgBlob[i].cbData);
1269 pbEncoded += setOf.rgBlob[i].cbData;
1273 for (i = 0; i < setOf.cBlob; i++)
1274 CryptMemFree(setOf.rgBlob[i].pbData);
1275 CryptMemFree(setOf.rgBlob);
1276 return ret;
1279 static BOOL CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
1280 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1281 DWORD *pcbEncoded)
1283 BOOL ret;
1284 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1286 __TRY
1288 DWORD i;
1290 ret = TRUE;
1291 if (rdn->cRDNAttr)
1293 setOf.cBlob = rdn->cRDNAttr;
1294 setOf.rgBlob = CryptMemAlloc(rdn->cRDNAttr *
1295 sizeof(CRYPT_DER_BLOB));
1296 if (!setOf.rgBlob)
1297 ret = FALSE;
1298 else
1299 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1301 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1303 setOf.rgBlob[i].cbData = 0;
1304 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1305 nameValueEncodeFunc, NULL, &setOf.rgBlob[i].cbData);
1306 if (ret)
1308 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1309 if (!setOf.rgBlob[i].pbData)
1310 ret = FALSE;
1311 else
1312 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1313 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1314 setOf.rgBlob[i].pbData, &setOf.rgBlob[i].cbData);
1316 if (!ret)
1318 /* Have to propagate index of failing character */
1319 *pcbEncoded = setOf.rgBlob[i].cbData;
1322 if (ret)
1323 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1324 pbEncoded, pcbEncoded);
1325 for (i = 0; i < setOf.cBlob; i++)
1326 CryptMemFree(setOf.rgBlob[i].pbData);
1328 __EXCEPT_PAGE_FAULT
1330 SetLastError(STATUS_ACCESS_VIOLATION);
1331 ret = FALSE;
1333 __ENDTRY
1334 CryptMemFree(setOf.rgBlob);
1335 return ret;
1338 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1339 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1340 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1342 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1343 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1344 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1345 DWORD *pcbEncoded)
1347 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1348 BOOL ret;
1350 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1351 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1352 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1353 else
1354 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1355 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1356 return ret;
1359 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1360 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1361 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1363 BOOL ret = TRUE;
1365 __TRY
1367 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1368 DWORD bytesNeeded = 0, lenBytes, size, i;
1370 TRACE("encoding name with %d RDNs\n", info->cRDN);
1371 ret = TRUE;
1372 for (i = 0; ret && i < info->cRDN; i++)
1374 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1375 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1376 if (ret)
1377 bytesNeeded += size;
1378 else
1379 *pcbEncoded = size;
1381 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1382 bytesNeeded += 1 + lenBytes;
1383 if (ret)
1385 if (!pbEncoded)
1386 *pcbEncoded = bytesNeeded;
1387 else
1389 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1390 pbEncoded, pcbEncoded, bytesNeeded)))
1392 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1393 pbEncoded = *(BYTE **)pbEncoded;
1394 *pbEncoded++ = ASN_SEQUENCEOF;
1395 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1396 &lenBytes);
1397 pbEncoded += lenBytes;
1398 for (i = 0; ret && i < info->cRDN; i++)
1400 size = bytesNeeded;
1401 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1402 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1403 pbEncoded, &size);
1404 if (ret)
1406 pbEncoded += size;
1407 bytesNeeded -= size;
1409 else
1410 *pcbEncoded = size;
1416 __EXCEPT_PAGE_FAULT
1418 SetLastError(STATUS_ACCESS_VIOLATION);
1419 ret = FALSE;
1421 __ENDTRY
1422 return ret;
1425 static BOOL WINAPI CRYPT_AsnEncodeCTLVersion(DWORD dwCertEncodingType,
1426 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1427 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1429 const DWORD *ver = (const DWORD *)pvStructInfo;
1430 BOOL ret;
1432 /* CTL_V1 is not encoded */
1433 if (*ver == CTL_V1)
1435 *pcbEncoded = 0;
1436 ret = TRUE;
1438 else
1439 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
1440 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1441 return ret;
1444 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
1445 * if they are empty and the OID is not empty (otherwise omits them.)
1447 static BOOL WINAPI CRYPT_AsnEncodeCTLSubjectAlgorithm(
1448 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1449 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1450 DWORD *pcbEncoded)
1452 const CRYPT_ALGORITHM_IDENTIFIER *algo =
1453 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1454 BOOL ret;
1455 struct AsnEncodeSequenceItem items[2] = {
1456 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
1458 DWORD cItem = 1;
1460 if (algo->pszObjId)
1462 static const BYTE asn1Null[] = { ASN_NULL, 0 };
1463 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
1464 (LPBYTE)asn1Null };
1466 if (algo->Parameters.cbData)
1467 items[cItem].pvStructInfo = &algo->Parameters;
1468 else
1469 items[cItem].pvStructInfo = &nullBlob;
1470 items[cItem].encodeFunc = CRYPT_CopyEncodedBlob;
1471 cItem++;
1473 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1474 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1475 return ret;
1478 static BOOL CRYPT_AsnEncodeCTLEntry(const CTL_ENTRY *entry,
1479 BYTE *pbEncoded, DWORD *pcbEncoded)
1481 struct AsnEncodeSequenceItem items[2] = {
1482 { &entry->SubjectIdentifier, CRYPT_AsnEncodeOctets, 0 },
1483 { &entry->cAttribute, CRYPT_AsnEncodePKCSAttributes, 0 },
1485 BOOL ret;
1487 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1488 sizeof(items) / sizeof(items[0]), 0, NULL, pbEncoded, pcbEncoded);
1489 return ret;
1492 struct CTLEntries
1494 DWORD cEntry;
1495 CTL_ENTRY *rgEntry;
1498 static BOOL WINAPI CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType,
1499 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1500 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1502 BOOL ret;
1503 DWORD bytesNeeded, dataLen, lenBytes, i;
1504 const struct CTLEntries *entries = (const struct CTLEntries *)pvStructInfo;
1506 ret = TRUE;
1507 for (i = 0, dataLen = 0; ret && i < entries->cEntry; i++)
1509 DWORD size;
1511 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i], NULL, &size);
1512 if (ret)
1513 dataLen += size;
1515 if (ret)
1517 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1518 bytesNeeded = 1 + lenBytes + dataLen;
1519 if (!pbEncoded)
1520 *pcbEncoded = bytesNeeded;
1521 else
1523 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1524 pbEncoded, pcbEncoded, bytesNeeded)))
1526 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1527 pbEncoded = *(BYTE **)pbEncoded;
1528 *pbEncoded++ = ASN_SEQUENCEOF;
1529 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1530 pbEncoded += lenBytes;
1531 for (i = 0; ret && i < entries->cEntry; i++)
1533 DWORD size = dataLen;
1535 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i],
1536 pbEncoded, &size);
1537 pbEncoded += size;
1538 dataLen -= size;
1543 return ret;
1546 static BOOL WINAPI CRYPT_AsnEncodeCTL(DWORD dwCertEncodingType,
1547 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1548 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1550 BOOL ret = FALSE;
1552 __TRY
1554 const CTL_INFO *info = (const CTL_INFO *)pvStructInfo;
1555 struct AsnEncodeSequenceItem items[9] = {
1556 { &info->dwVersion, CRYPT_AsnEncodeCTLVersion, 0 },
1557 { &info->SubjectUsage, CRYPT_AsnEncodeEnhancedKeyUsage, 0 },
1559 struct AsnConstructedItem constructed = { 0 };
1560 DWORD cItem = 2;
1562 if (info->ListIdentifier.cbData)
1564 items[cItem].pvStructInfo = &info->ListIdentifier;
1565 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
1566 cItem++;
1568 if (info->SequenceNumber.cbData)
1570 items[cItem].pvStructInfo = &info->SequenceNumber;
1571 items[cItem].encodeFunc = CRYPT_AsnEncodeInteger;
1572 cItem++;
1574 items[cItem].pvStructInfo = &info->ThisUpdate;
1575 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1576 cItem++;
1577 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
1579 items[cItem].pvStructInfo = &info->NextUpdate;
1580 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1581 cItem++;
1583 items[cItem].pvStructInfo = &info->SubjectAlgorithm;
1584 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLSubjectAlgorithm;
1585 cItem++;
1586 if (info->cCTLEntry)
1588 items[cItem].pvStructInfo = &info->cCTLEntry;
1589 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLEntries;
1590 cItem++;
1592 if (info->cExtension)
1594 constructed.tag = 0;
1595 constructed.pvStructInfo = &info->cExtension;
1596 constructed.encodeFunc = CRYPT_AsnEncodeExtensions;
1597 items[cItem].pvStructInfo = &constructed;
1598 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1599 cItem++;
1601 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1602 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1604 __EXCEPT_PAGE_FAULT
1606 SetLastError(STATUS_ACCESS_VIOLATION);
1608 __ENDTRY
1609 return ret;
1612 static BOOL CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType,
1613 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1614 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1616 BOOL ret = FALSE;
1618 __TRY
1620 const CRYPT_SMIME_CAPABILITY *capability =
1621 (const CRYPT_SMIME_CAPABILITY *)pvStructInfo;
1623 if (!capability->pszObjId)
1624 SetLastError(E_INVALIDARG);
1625 else
1627 struct AsnEncodeSequenceItem items[] = {
1628 { capability->pszObjId, CRYPT_AsnEncodeOid, 0 },
1629 { &capability->Parameters, CRYPT_CopyEncodedBlob, 0 },
1632 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1633 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1634 pcbEncoded);
1637 __EXCEPT_PAGE_FAULT
1639 SetLastError(STATUS_ACCESS_VIOLATION);
1641 __ENDTRY
1642 return ret;
1645 static BOOL WINAPI CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType,
1646 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1647 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1649 BOOL ret = FALSE;
1651 __TRY
1653 DWORD bytesNeeded, dataLen, lenBytes, i;
1654 const CRYPT_SMIME_CAPABILITIES *capabilities =
1655 (const CRYPT_SMIME_CAPABILITIES *)pvStructInfo;
1657 ret = TRUE;
1658 for (i = 0, dataLen = 0; ret && i < capabilities->cCapability; i++)
1660 DWORD size;
1662 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType, NULL,
1663 &capabilities->rgCapability[i], 0, NULL, NULL, &size);
1664 if (ret)
1665 dataLen += size;
1667 if (ret)
1669 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1670 bytesNeeded = 1 + lenBytes + dataLen;
1671 if (!pbEncoded)
1672 *pcbEncoded = bytesNeeded;
1673 else
1675 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1676 pbEncoded, pcbEncoded, bytesNeeded)))
1678 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1679 pbEncoded = *(BYTE **)pbEncoded;
1680 *pbEncoded++ = ASN_SEQUENCEOF;
1681 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1682 pbEncoded += lenBytes;
1683 for (i = 0; i < capabilities->cCapability; i++)
1685 DWORD size = dataLen;
1687 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType,
1688 NULL, &capabilities->rgCapability[i], 0, NULL,
1689 pbEncoded, &size);
1690 pbEncoded += size;
1691 dataLen -= size;
1697 __EXCEPT_PAGE_FAULT
1699 SetLastError(STATUS_ACCESS_VIOLATION);
1701 __ENDTRY
1702 return ret;
1705 static BOOL WINAPI CRYPT_AsnEncodeNoticeNumbers(DWORD dwCertEncodingType,
1706 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1707 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1709 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
1710 DWORD bytesNeeded, dataLen, lenBytes, i;
1711 BOOL ret = TRUE;
1713 for (i = 0, dataLen = 0; ret && i < noticeRef->cNoticeNumbers; i++)
1715 DWORD size;
1717 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
1718 &noticeRef->rgNoticeNumbers[i], 0, NULL, NULL, &size);
1719 if (ret)
1720 dataLen += size;
1722 if (ret)
1724 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1725 bytesNeeded = 1 + lenBytes + dataLen;
1726 if (!pbEncoded)
1727 *pcbEncoded = bytesNeeded;
1728 else
1730 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1731 pcbEncoded, bytesNeeded)))
1733 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1734 pbEncoded = *(BYTE **)pbEncoded;
1735 *pbEncoded++ = ASN_SEQUENCE;
1736 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1737 pbEncoded += lenBytes;
1738 for (i = 0; i < noticeRef->cNoticeNumbers; i++)
1740 DWORD size = dataLen;
1742 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
1743 &noticeRef->rgNoticeNumbers[i], 0, NULL, pbEncoded, &size);
1744 pbEncoded += size;
1745 dataLen -= size;
1750 return ret;
1753 static BOOL WINAPI CRYPT_AsnEncodeNoticeReference(DWORD dwCertEncodingType,
1754 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1755 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1757 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
1758 BOOL ret;
1759 CERT_NAME_VALUE orgValue = { CERT_RDN_IA5_STRING,
1760 { 0, (LPBYTE)noticeRef->pszOrganization } };
1761 struct AsnEncodeSequenceItem items[] = {
1762 { &orgValue, CRYPT_AsnEncodeNameValue, 0 },
1763 { noticeRef, CRYPT_AsnEncodeNoticeNumbers, 0 },
1766 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1767 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1768 pcbEncoded);
1769 return ret;
1772 static BOOL WINAPI CRYPT_AsnEncodePolicyQualifierUserNotice(
1773 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1774 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1775 DWORD *pcbEncoded)
1777 BOOL ret = FALSE;
1779 __TRY
1781 const CERT_POLICY_QUALIFIER_USER_NOTICE *notice = pvStructInfo;
1782 struct AsnEncodeSequenceItem items[2];
1783 CERT_NAME_VALUE displayTextValue;
1784 DWORD cItem = 0;
1786 ret = TRUE;
1787 if (notice->pNoticeReference)
1789 items[cItem].encodeFunc = CRYPT_AsnEncodeNoticeReference;
1790 items[cItem].pvStructInfo = notice->pNoticeReference;
1791 cItem++;
1793 if (notice->pszDisplayText)
1795 displayTextValue.dwValueType = CERT_RDN_BMP_STRING;
1796 displayTextValue.Value.cbData = 0;
1797 displayTextValue.Value.pbData = (LPBYTE)notice->pszDisplayText;
1798 items[cItem].encodeFunc = CRYPT_AsnEncodeNameValue;
1799 items[cItem].pvStructInfo = &displayTextValue;
1800 cItem++;
1802 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1803 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1805 __EXCEPT_PAGE_FAULT
1807 SetLastError(STATUS_ACCESS_VIOLATION);
1809 __ENDTRY
1810 return ret;
1813 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1814 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1815 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1817 BOOL ret = FALSE;
1819 __TRY
1821 const CRYPT_ATTRIBUTE *attr = (const CRYPT_ATTRIBUTE *)pvStructInfo;
1823 if (!attr->pszObjId)
1824 SetLastError(E_INVALIDARG);
1825 else
1827 struct AsnEncodeSequenceItem items[2] = {
1828 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1829 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1832 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1833 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1834 pcbEncoded);
1837 __EXCEPT_PAGE_FAULT
1839 SetLastError(STATUS_ACCESS_VIOLATION);
1841 __ENDTRY
1842 return ret;
1845 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1846 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1847 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1849 BOOL ret = FALSE;
1851 __TRY
1853 const CRYPT_ATTRIBUTES *attributes =
1854 (const CRYPT_ATTRIBUTES *)pvStructInfo;
1855 struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
1856 sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
1858 ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
1859 &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1861 __EXCEPT_PAGE_FAULT
1863 SetLastError(STATUS_ACCESS_VIOLATION);
1865 __ENDTRY
1866 return ret;
1869 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1870 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
1871 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1872 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1873 DWORD *pcbEncoded)
1875 const CRYPT_CONTENT_INFO *info = (const CRYPT_CONTENT_INFO *)pvStructInfo;
1876 struct AsnEncodeSequenceItem items[2] = {
1877 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1878 { NULL, NULL, 0 },
1880 struct AsnConstructedItem constructed = { 0 };
1881 DWORD cItem = 1;
1883 if (info->Content.cbData)
1885 constructed.tag = 0;
1886 constructed.pvStructInfo = &info->Content;
1887 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1888 items[cItem].pvStructInfo = &constructed;
1889 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1890 cItem++;
1892 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1893 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1896 BOOL CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA *digestedData,
1897 void *pvData, DWORD *pcbData)
1899 struct AsnEncodeSequenceItem items[] = {
1900 { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1901 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
1902 0 },
1903 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1904 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1907 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1908 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
1911 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1912 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1913 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1915 BOOL ret = FALSE;
1917 __TRY
1919 const CRYPT_CONTENT_INFO *info =
1920 (const CRYPT_CONTENT_INFO *)pvStructInfo;
1922 if (!info->pszObjId)
1923 SetLastError(E_INVALIDARG);
1924 else
1925 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
1926 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1927 pcbEncoded);
1929 __EXCEPT_PAGE_FAULT
1931 SetLastError(STATUS_ACCESS_VIOLATION);
1933 __ENDTRY
1934 return ret;
1937 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1938 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1939 DWORD *pcbEncoded)
1941 BOOL ret = TRUE;
1942 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1943 DWORD bytesNeeded, lenBytes, encodedLen;
1945 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1946 strlenW(str);
1947 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1948 bytesNeeded = 1 + lenBytes + encodedLen;
1949 if (!pbEncoded)
1950 *pcbEncoded = bytesNeeded;
1951 else
1953 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1954 pbEncoded, pcbEncoded, bytesNeeded)))
1956 DWORD i;
1958 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1959 pbEncoded = *(BYTE **)pbEncoded;
1960 *pbEncoded++ = tag;
1961 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1962 pbEncoded += lenBytes;
1963 for (i = 0; i < encodedLen; i++)
1964 *pbEncoded++ = (BYTE)str[i];
1967 return ret;
1970 static void CRYPT_FreeSpace(PCRYPT_ENCODE_PARA pEncodePara, LPVOID pv)
1972 if (pEncodePara && pEncodePara->pfnFree)
1973 pEncodePara->pfnFree(pv);
1974 else
1975 LocalFree(pv);
1978 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
1979 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1980 DWORD *pcbEncoded)
1982 BOOL ret = TRUE;
1983 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1984 DWORD bytesNeeded, lenBytes, encodedLen;
1986 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1987 strlenW(str);
1988 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1989 bytesNeeded = 1 + lenBytes + encodedLen;
1990 if (!pbEncoded)
1991 *pcbEncoded = bytesNeeded;
1992 else
1994 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1995 pbEncoded, pcbEncoded, bytesNeeded)))
1997 DWORD i;
1998 BYTE *ptr;
2000 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2001 ptr = *(BYTE **)pbEncoded;
2002 else
2003 ptr = pbEncoded;
2004 *ptr++ = ASN_NUMERICSTRING;
2005 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2006 ptr += lenBytes;
2007 for (i = 0; ret && i < encodedLen; i++)
2009 if (isdigitW(str[i]))
2010 *ptr++ = (BYTE)str[i];
2011 else
2013 *pcbEncoded = i;
2014 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
2015 ret = FALSE;
2018 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2019 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2022 return ret;
2025 static inline int isprintableW(WCHAR wc)
2027 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
2028 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
2029 wc == '/' || wc == ':' || wc == '=' || wc == '?';
2032 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
2033 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
2034 DWORD *pcbEncoded)
2036 BOOL ret = TRUE;
2037 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2038 DWORD bytesNeeded, lenBytes, encodedLen;
2040 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
2041 strlenW(str);
2042 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2043 bytesNeeded = 1 + lenBytes + encodedLen;
2044 if (!pbEncoded)
2045 *pcbEncoded = bytesNeeded;
2046 else
2048 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2049 pbEncoded, pcbEncoded, bytesNeeded)))
2051 DWORD i;
2052 BYTE *ptr;
2054 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2055 ptr = *(BYTE **)pbEncoded;
2056 else
2057 ptr = pbEncoded;
2058 *ptr++ = ASN_PRINTABLESTRING;
2059 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2060 ptr += lenBytes;
2061 for (i = 0; ret && i < encodedLen; i++)
2063 if (isprintableW(str[i]))
2064 *ptr++ = (BYTE)str[i];
2065 else
2067 *pcbEncoded = i;
2068 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
2069 ret = FALSE;
2072 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2073 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2076 return ret;
2079 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
2080 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
2081 DWORD *pcbEncoded)
2083 BOOL ret = TRUE;
2084 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2085 DWORD bytesNeeded, lenBytes, encodedLen;
2087 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
2088 strlenW(str);
2089 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2090 bytesNeeded = 1 + lenBytes + encodedLen;
2091 if (!pbEncoded)
2092 *pcbEncoded = bytesNeeded;
2093 else
2095 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2096 pbEncoded, pcbEncoded, bytesNeeded)))
2098 DWORD i;
2099 BYTE *ptr;
2101 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2102 ptr = *(BYTE **)pbEncoded;
2103 else
2104 ptr = pbEncoded;
2105 *ptr++ = ASN_IA5STRING;
2106 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2107 ptr += lenBytes;
2108 for (i = 0; ret && i < encodedLen; i++)
2110 if (str[i] <= 0x7f)
2111 *ptr++ = (BYTE)str[i];
2112 else
2114 *pcbEncoded = i;
2115 SetLastError(CRYPT_E_INVALID_IA5_STRING);
2116 ret = FALSE;
2119 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2120 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2123 return ret;
2126 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
2127 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
2128 DWORD *pcbEncoded)
2130 BOOL ret = TRUE;
2131 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2132 DWORD bytesNeeded, lenBytes, strLen;
2134 /* FIXME: doesn't handle composite characters */
2135 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
2136 strlenW(str);
2137 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
2138 bytesNeeded = 1 + lenBytes + strLen * 4;
2139 if (!pbEncoded)
2140 *pcbEncoded = bytesNeeded;
2141 else
2143 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2144 pbEncoded, pcbEncoded, bytesNeeded)))
2146 DWORD i;
2148 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2149 pbEncoded = *(BYTE **)pbEncoded;
2150 *pbEncoded++ = ASN_UNIVERSALSTRING;
2151 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
2152 pbEncoded += lenBytes;
2153 for (i = 0; i < strLen; i++)
2155 *pbEncoded++ = 0;
2156 *pbEncoded++ = 0;
2157 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
2158 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
2162 return ret;
2165 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
2166 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2167 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2169 BOOL ret = FALSE;
2171 __TRY
2173 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
2175 switch (value->dwValueType)
2177 case CERT_RDN_ANY_TYPE:
2178 case CERT_RDN_ENCODED_BLOB:
2179 case CERT_RDN_OCTET_STRING:
2180 SetLastError(CRYPT_E_NOT_CHAR_STRING);
2181 break;
2182 case CERT_RDN_NUMERIC_STRING:
2183 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
2184 pbEncoded, pcbEncoded);
2185 break;
2186 case CERT_RDN_PRINTABLE_STRING:
2187 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
2188 pbEncoded, pcbEncoded);
2189 break;
2190 case CERT_RDN_TELETEX_STRING:
2191 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
2192 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2193 break;
2194 case CERT_RDN_VIDEOTEX_STRING:
2195 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
2196 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2197 break;
2198 case CERT_RDN_IA5_STRING:
2199 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
2200 pbEncoded, pcbEncoded);
2201 break;
2202 case CERT_RDN_GRAPHIC_STRING:
2203 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
2204 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2205 break;
2206 case CERT_RDN_VISIBLE_STRING:
2207 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
2208 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2209 break;
2210 case CERT_RDN_GENERAL_STRING:
2211 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
2212 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2213 break;
2214 case CERT_RDN_UNIVERSAL_STRING:
2215 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
2216 pbEncoded, pcbEncoded);
2217 break;
2218 case CERT_RDN_BMP_STRING:
2219 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
2220 pbEncoded, pcbEncoded);
2221 break;
2222 case CERT_RDN_UTF8_STRING:
2223 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
2224 pbEncoded, pcbEncoded);
2225 break;
2226 default:
2227 SetLastError(CRYPT_E_ASN1_CHOICE);
2230 __EXCEPT_PAGE_FAULT
2232 SetLastError(STATUS_ACCESS_VIOLATION);
2234 __ENDTRY
2235 return ret;
2238 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
2239 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2240 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2242 BOOL ret;
2244 __TRY
2246 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
2247 DWORD bytesNeeded = 0, lenBytes, size, i;
2249 TRACE("encoding name with %d RDNs\n", info->cRDN);
2250 ret = TRUE;
2251 for (i = 0; ret && i < info->cRDN; i++)
2253 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
2254 CRYPT_AsnEncodeNameValue, NULL, &size);
2255 if (ret)
2256 bytesNeeded += size;
2258 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2259 bytesNeeded += 1 + lenBytes;
2260 if (ret)
2262 if (!pbEncoded)
2263 *pcbEncoded = bytesNeeded;
2264 else
2266 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2267 pbEncoded, pcbEncoded, bytesNeeded)))
2269 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2270 pbEncoded = *(BYTE **)pbEncoded;
2271 *pbEncoded++ = ASN_SEQUENCEOF;
2272 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
2273 &lenBytes);
2274 pbEncoded += lenBytes;
2275 for (i = 0; ret && i < info->cRDN; i++)
2277 size = bytesNeeded;
2278 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
2279 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, pbEncoded,
2280 &size);
2281 if (ret)
2283 pbEncoded += size;
2284 bytesNeeded -= size;
2291 __EXCEPT_PAGE_FAULT
2293 SetLastError(STATUS_ACCESS_VIOLATION);
2294 ret = FALSE;
2296 __ENDTRY
2297 return ret;
2300 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
2301 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2302 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2304 BOOL val = *(const BOOL *)pvStructInfo, ret;
2306 TRACE("%d\n", val);
2308 if (!pbEncoded)
2310 *pcbEncoded = 3;
2311 ret = TRUE;
2313 else if (*pcbEncoded < 3)
2315 *pcbEncoded = 3;
2316 SetLastError(ERROR_MORE_DATA);
2317 ret = FALSE;
2319 else
2321 *pcbEncoded = 3;
2322 *pbEncoded++ = ASN_BOOL;
2323 *pbEncoded++ = 1;
2324 *pbEncoded++ = val ? 0xff : 0;
2325 ret = TRUE;
2327 TRACE("returning %d (%08x)\n", ret, GetLastError());
2328 return ret;
2331 static BOOL WINAPI CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType,
2332 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2333 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2335 const CERT_ALT_NAME_ENTRY *entry =
2336 (const CERT_ALT_NAME_ENTRY *)pvStructInfo;
2337 BOOL ret;
2338 DWORD dataLen;
2339 BYTE tag;
2341 ret = TRUE;
2342 switch (entry->dwAltNameChoice)
2344 case CERT_ALT_NAME_RFC822_NAME:
2345 case CERT_ALT_NAME_DNS_NAME:
2346 case CERT_ALT_NAME_URL:
2347 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2348 if (entry->u.pwszURL)
2350 DWORD i;
2352 /* Not + 1: don't encode the NULL-terminator */
2353 dataLen = lstrlenW(entry->u.pwszURL);
2354 for (i = 0; ret && i < dataLen; i++)
2356 if (entry->u.pwszURL[i] > 0x7f)
2358 SetLastError(CRYPT_E_INVALID_IA5_STRING);
2359 ret = FALSE;
2360 *pcbEncoded = i;
2364 else
2365 dataLen = 0;
2366 break;
2367 case CERT_ALT_NAME_DIRECTORY_NAME:
2368 tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1);
2369 dataLen = entry->u.DirectoryName.cbData;
2370 break;
2371 case CERT_ALT_NAME_IP_ADDRESS:
2372 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2373 dataLen = entry->u.IPAddress.cbData;
2374 break;
2375 case CERT_ALT_NAME_REGISTERED_ID:
2377 struct AsnEncodeTagSwappedItem swapped =
2378 { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID,
2379 CRYPT_AsnEncodeOid };
2381 return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded,
2382 pcbEncoded);
2384 case CERT_ALT_NAME_OTHER_NAME:
2385 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
2386 return FALSE;
2387 default:
2388 SetLastError(E_INVALIDARG);
2389 return FALSE;
2391 if (ret)
2393 DWORD bytesNeeded, lenBytes;
2395 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2396 bytesNeeded = 1 + dataLen + lenBytes;
2397 if (!pbEncoded)
2398 *pcbEncoded = bytesNeeded;
2399 else if (*pcbEncoded < bytesNeeded)
2401 SetLastError(ERROR_MORE_DATA);
2402 *pcbEncoded = bytesNeeded;
2403 ret = FALSE;
2405 else
2407 *pbEncoded++ = tag;
2408 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2409 pbEncoded += lenBytes;
2410 switch (entry->dwAltNameChoice)
2412 case CERT_ALT_NAME_RFC822_NAME:
2413 case CERT_ALT_NAME_DNS_NAME:
2414 case CERT_ALT_NAME_URL:
2416 DWORD i;
2418 for (i = 0; i < dataLen; i++)
2419 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
2420 break;
2422 case CERT_ALT_NAME_DIRECTORY_NAME:
2423 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen);
2424 break;
2425 case CERT_ALT_NAME_IP_ADDRESS:
2426 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
2427 break;
2429 if (ret)
2430 *pcbEncoded = bytesNeeded;
2433 TRACE("returning %d (%08x)\n", ret, GetLastError());
2434 return ret;
2437 static BOOL WINAPI CRYPT_AsnEncodeIntegerSwapBytes(DWORD dwCertEncodingType,
2438 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2439 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2441 BOOL ret;
2443 __TRY
2445 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2446 CRYPT_DATA_BLOB newBlob = { blob->cbData, NULL };
2448 ret = TRUE;
2449 if (newBlob.cbData)
2451 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2452 if (newBlob.pbData)
2454 DWORD i;
2456 for (i = 0; i < newBlob.cbData; i++)
2457 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2459 else
2460 ret = FALSE;
2462 if (ret)
2463 ret = CRYPT_AsnEncodeInteger(dwCertEncodingType, lpszStructType,
2464 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2465 CryptMemFree(newBlob.pbData);
2467 __EXCEPT_PAGE_FAULT
2469 SetLastError(STATUS_ACCESS_VIOLATION);
2470 ret = FALSE;
2472 __ENDTRY
2473 return ret;
2476 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
2477 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2478 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2480 BOOL ret;
2482 __TRY
2484 const CERT_AUTHORITY_KEY_ID_INFO *info =
2485 (const CERT_AUTHORITY_KEY_ID_INFO *)pvStructInfo;
2486 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2487 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2488 struct AsnConstructedItem constructed = { 0 };
2489 DWORD cItem = 0, cSwapped = 0;
2491 if (info->KeyId.cbData)
2493 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2494 swapped[cSwapped].pvStructInfo = &info->KeyId;
2495 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2496 items[cItem].pvStructInfo = &swapped[cSwapped];
2497 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2498 cSwapped++;
2499 cItem++;
2501 if (info->CertIssuer.cbData)
2503 constructed.tag = 1;
2504 constructed.pvStructInfo = &info->CertIssuer;
2505 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2506 items[cItem].pvStructInfo = &constructed;
2507 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2508 cItem++;
2510 if (info->CertSerialNumber.cbData)
2512 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2513 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2514 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2515 items[cItem].pvStructInfo = &swapped[cSwapped];
2516 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2517 cSwapped++;
2518 cItem++;
2520 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2521 pEncodePara, pbEncoded, pcbEncoded);
2523 __EXCEPT_PAGE_FAULT
2525 SetLastError(STATUS_ACCESS_VIOLATION);
2526 ret = FALSE;
2528 __ENDTRY
2529 return ret;
2532 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2533 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2534 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2536 BOOL ret;
2538 __TRY
2540 const CERT_ALT_NAME_INFO *info =
2541 (const CERT_ALT_NAME_INFO *)pvStructInfo;
2542 DWORD bytesNeeded, dataLen, lenBytes, i;
2544 ret = TRUE;
2545 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2546 * can't encode an erroneous entry index if it's bigger than this.
2548 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2550 DWORD len;
2552 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, NULL,
2553 &info->rgAltEntry[i], 0, NULL, NULL, &len);
2554 if (ret)
2555 dataLen += len;
2556 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2558 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2559 * the bad character, now set the index of the bad
2560 * entry
2562 *pcbEncoded = (BYTE)i <<
2563 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2566 if (ret)
2568 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2569 bytesNeeded = 1 + lenBytes + dataLen;
2570 if (!pbEncoded)
2572 *pcbEncoded = bytesNeeded;
2573 ret = TRUE;
2575 else
2577 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2578 pbEncoded, pcbEncoded, bytesNeeded)))
2580 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2581 pbEncoded = *(BYTE **)pbEncoded;
2582 *pbEncoded++ = ASN_SEQUENCEOF;
2583 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2584 pbEncoded += lenBytes;
2585 for (i = 0; ret && i < info->cAltEntry; i++)
2587 DWORD len = dataLen;
2589 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType,
2590 NULL, &info->rgAltEntry[i], 0, NULL, pbEncoded, &len);
2591 if (ret)
2593 pbEncoded += len;
2594 dataLen -= len;
2601 __EXCEPT_PAGE_FAULT
2603 SetLastError(STATUS_ACCESS_VIOLATION);
2604 ret = FALSE;
2606 __ENDTRY
2607 return ret;
2610 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2611 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2612 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2614 BOOL ret;
2616 __TRY
2618 const CERT_AUTHORITY_KEY_ID2_INFO *info =
2619 (const CERT_AUTHORITY_KEY_ID2_INFO *)pvStructInfo;
2620 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2621 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2622 DWORD cItem = 0, cSwapped = 0;
2624 if (info->KeyId.cbData)
2626 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2627 swapped[cSwapped].pvStructInfo = &info->KeyId;
2628 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2629 items[cItem].pvStructInfo = &swapped[cSwapped];
2630 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2631 cSwapped++;
2632 cItem++;
2634 if (info->AuthorityCertIssuer.cAltEntry)
2636 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2637 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2638 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2639 items[cItem].pvStructInfo = &swapped[cSwapped];
2640 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2641 cSwapped++;
2642 cItem++;
2644 if (info->AuthorityCertSerialNumber.cbData)
2646 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2647 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2648 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2649 items[cItem].pvStructInfo = &swapped[cSwapped];
2650 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2651 cSwapped++;
2652 cItem++;
2654 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2655 pEncodePara, pbEncoded, pcbEncoded);
2657 __EXCEPT_PAGE_FAULT
2659 SetLastError(STATUS_ACCESS_VIOLATION);
2660 ret = FALSE;
2662 __ENDTRY
2663 return ret;
2666 static BOOL CRYPT_AsnEncodeAccessDescription(
2667 const CERT_ACCESS_DESCRIPTION *descr, BYTE *pbEncoded, DWORD *pcbEncoded)
2669 struct AsnEncodeSequenceItem items[] = {
2670 { descr->pszAccessMethod, CRYPT_AsnEncodeOid, 0 },
2671 { &descr->AccessLocation, CRYPT_AsnEncodeAltNameEntry, 0 },
2674 if (!descr->pszAccessMethod)
2676 SetLastError(E_INVALIDARG);
2677 return FALSE;
2679 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
2680 sizeof(items) / sizeof(items[0]), 0, NULL, pbEncoded, pcbEncoded);
2683 static BOOL WINAPI CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType,
2684 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2685 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2687 BOOL ret;
2689 __TRY
2691 DWORD bytesNeeded, dataLen, lenBytes, i;
2692 const CERT_AUTHORITY_INFO_ACCESS *info =
2693 (const CERT_AUTHORITY_INFO_ACCESS *)pvStructInfo;
2695 ret = TRUE;
2696 for (i = 0, dataLen = 0; ret && i < info->cAccDescr; i++)
2698 DWORD size;
2700 ret = CRYPT_AsnEncodeAccessDescription(&info->rgAccDescr[i], NULL,
2701 &size);
2702 if (ret)
2703 dataLen += size;
2705 if (ret)
2707 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2708 bytesNeeded = 1 + lenBytes + dataLen;
2709 if (!pbEncoded)
2710 *pcbEncoded = bytesNeeded;
2711 else
2713 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2714 pbEncoded, pcbEncoded, bytesNeeded)))
2716 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2717 pbEncoded = *(BYTE **)pbEncoded;
2718 *pbEncoded++ = ASN_SEQUENCEOF;
2719 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2720 pbEncoded += lenBytes;
2721 for (i = 0; i < info->cAccDescr; i++)
2723 DWORD size = dataLen;
2725 ret = CRYPT_AsnEncodeAccessDescription(
2726 &info->rgAccDescr[i], pbEncoded, &size);
2727 pbEncoded += size;
2728 dataLen -= size;
2734 __EXCEPT_PAGE_FAULT
2736 SetLastError(STATUS_ACCESS_VIOLATION);
2737 ret = FALSE;
2739 __ENDTRY
2740 return ret;
2743 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2744 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2745 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2747 BOOL ret;
2749 __TRY
2751 const CERT_BASIC_CONSTRAINTS_INFO *info =
2752 (const CERT_BASIC_CONSTRAINTS_INFO *)pvStructInfo;
2753 struct AsnEncodeSequenceItem items[3] = {
2754 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2755 { 0 }
2757 DWORD cItem = 1;
2759 if (info->fPathLenConstraint)
2761 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2762 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2763 cItem++;
2765 if (info->cSubtreesConstraint)
2767 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2768 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2769 cItem++;
2771 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2772 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2774 __EXCEPT_PAGE_FAULT
2776 SetLastError(STATUS_ACCESS_VIOLATION);
2777 ret = FALSE;
2779 __ENDTRY
2780 return ret;
2783 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2784 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2785 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2787 BOOL ret;
2789 __TRY
2791 const CERT_BASIC_CONSTRAINTS2_INFO *info =
2792 (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
2793 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2794 DWORD cItem = 0;
2796 if (info->fCA)
2798 items[cItem].pvStructInfo = &info->fCA;
2799 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2800 cItem++;
2802 if (info->fPathLenConstraint)
2804 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2805 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2806 cItem++;
2808 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2809 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2811 __EXCEPT_PAGE_FAULT
2813 SetLastError(STATUS_ACCESS_VIOLATION);
2814 ret = FALSE;
2816 __ENDTRY
2817 return ret;
2820 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType,
2821 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2822 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2824 DWORD cPolicyQualifier = *(DWORD *)pvStructInfo;
2825 const CERT_POLICY_QUALIFIER_INFO *rgPolicyQualifier =
2826 *(const CERT_POLICY_QUALIFIER_INFO **)
2827 ((LPBYTE)pvStructInfo + sizeof(DWORD));
2828 BOOL ret;
2830 if (!cPolicyQualifier)
2832 *pcbEncoded = 0;
2833 ret = TRUE;
2835 else
2837 struct AsnEncodeSequenceItem items[2] = {
2838 { NULL, CRYPT_AsnEncodeOid, 0 },
2839 { NULL, CRYPT_CopyEncodedBlob, 0 },
2841 DWORD bytesNeeded = 0, lenBytes, size, i;
2843 ret = TRUE;
2844 for (i = 0; ret && i < cPolicyQualifier; i++)
2846 items[0].pvStructInfo = rgPolicyQualifier[i].pszPolicyQualifierId;
2847 items[1].pvStructInfo = &rgPolicyQualifier[i].Qualifier;
2848 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2849 sizeof(items) / sizeof(items[0]),
2850 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
2851 if (ret)
2852 bytesNeeded += size;
2854 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2855 bytesNeeded += 1 + lenBytes;
2856 if (ret)
2858 if (!pbEncoded)
2859 *pcbEncoded = bytesNeeded;
2860 else
2862 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2863 pbEncoded, pcbEncoded, bytesNeeded)))
2865 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2866 pbEncoded = *(BYTE **)pbEncoded;
2867 *pbEncoded++ = ASN_SEQUENCEOF;
2868 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
2869 &lenBytes);
2870 pbEncoded += lenBytes;
2871 for (i = 0; ret && i < cPolicyQualifier; i++)
2873 items[0].pvStructInfo =
2874 rgPolicyQualifier[i].pszPolicyQualifierId;
2875 items[1].pvStructInfo =
2876 &rgPolicyQualifier[i].Qualifier;
2877 size = bytesNeeded;
2878 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2879 sizeof(items) / sizeof(items[0]),
2880 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
2881 &size);
2882 if (ret)
2884 pbEncoded += size;
2885 bytesNeeded -= size;
2892 return ret;
2895 static BOOL CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType,
2896 const CERT_POLICY_INFO *info, DWORD dwFlags, BYTE *pbEncoded,
2897 DWORD *pcbEncoded)
2899 struct AsnEncodeSequenceItem items[2] = {
2900 { info->pszPolicyIdentifier, CRYPT_AsnEncodeOid, 0 },
2901 { &info->cPolicyQualifier, CRYPT_AsnEncodeCertPolicyQualifiers, 0 },
2903 BOOL ret;
2905 if (!info->pszPolicyIdentifier)
2907 SetLastError(E_INVALIDARG);
2908 return FALSE;
2910 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2911 sizeof(items) / sizeof(items[0]), dwFlags, NULL, pbEncoded, pcbEncoded);
2912 return ret;
2915 static BOOL WINAPI CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType,
2916 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2917 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2919 BOOL ret = FALSE;
2921 __TRY
2923 const CERT_POLICIES_INFO *info = pvStructInfo;
2924 DWORD bytesNeeded = 0, lenBytes, size, i;
2926 ret = TRUE;
2927 for (i = 0; ret && i < info->cPolicyInfo; i++)
2929 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
2930 &info->rgPolicyInfo[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
2931 &size);
2932 if (ret)
2933 bytesNeeded += size;
2935 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2936 bytesNeeded += 1 + lenBytes;
2937 if (ret)
2939 if (!pbEncoded)
2940 *pcbEncoded = bytesNeeded;
2941 else
2943 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2944 pbEncoded, pcbEncoded, bytesNeeded)))
2946 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2947 pbEncoded = *(BYTE **)pbEncoded;
2948 *pbEncoded++ = ASN_SEQUENCEOF;
2949 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
2950 &lenBytes);
2951 pbEncoded += lenBytes;
2952 for (i = 0; ret && i < info->cPolicyInfo; i++)
2954 size = bytesNeeded;
2955 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
2956 &info->rgPolicyInfo[i],
2957 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pbEncoded, &size);
2958 if (ret)
2960 pbEncoded += size;
2961 bytesNeeded -= size;
2968 __EXCEPT_PAGE_FAULT
2970 SetLastError(STATUS_ACCESS_VIOLATION);
2972 __ENDTRY
2973 return ret;
2976 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
2977 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2978 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2980 BOOL ret;
2982 __TRY
2984 const BLOBHEADER *hdr =
2985 (const BLOBHEADER *)pvStructInfo;
2987 if (hdr->bType != PUBLICKEYBLOB)
2989 SetLastError(E_INVALIDARG);
2990 ret = FALSE;
2992 else
2994 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
2995 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
2996 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
2997 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
2998 struct AsnEncodeSequenceItem items[] = {
2999 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
3000 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
3003 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3004 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3005 pcbEncoded);
3008 __EXCEPT_PAGE_FAULT
3010 SetLastError(STATUS_ACCESS_VIOLATION);
3011 ret = FALSE;
3013 __ENDTRY
3014 return ret;
3017 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
3018 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3019 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3021 BOOL ret;
3023 __TRY
3025 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
3026 DWORD bytesNeeded, lenBytes;
3028 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
3029 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
3031 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
3032 bytesNeeded = 1 + lenBytes + blob->cbData;
3033 if (!pbEncoded)
3035 *pcbEncoded = bytesNeeded;
3036 ret = TRUE;
3038 else
3040 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3041 pcbEncoded, bytesNeeded)))
3043 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3044 pbEncoded = *(BYTE **)pbEncoded;
3045 *pbEncoded++ = ASN_OCTETSTRING;
3046 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
3047 pbEncoded += lenBytes;
3048 if (blob->cbData)
3049 memcpy(pbEncoded, blob->pbData, blob->cbData);
3053 __EXCEPT_PAGE_FAULT
3055 SetLastError(STATUS_ACCESS_VIOLATION);
3056 ret = FALSE;
3058 __ENDTRY
3059 TRACE("returning %d (%08x)\n", ret, GetLastError());
3060 return ret;
3063 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
3064 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3065 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3067 BOOL ret;
3069 __TRY
3071 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
3072 DWORD bytesNeeded, lenBytes, dataBytes;
3073 BYTE unusedBits;
3075 /* yep, MS allows cUnusedBits to be >= 8 */
3076 if (!blob->cUnusedBits)
3078 dataBytes = blob->cbData;
3079 unusedBits = 0;
3081 else if (blob->cbData * 8 > blob->cUnusedBits)
3083 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
3084 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
3085 blob->cUnusedBits;
3087 else
3089 dataBytes = 0;
3090 unusedBits = 0;
3092 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
3093 bytesNeeded = 1 + lenBytes + dataBytes + 1;
3094 if (!pbEncoded)
3096 *pcbEncoded = bytesNeeded;
3097 ret = TRUE;
3099 else
3101 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3102 pcbEncoded, bytesNeeded)))
3104 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3105 pbEncoded = *(BYTE **)pbEncoded;
3106 *pbEncoded++ = ASN_BITSTRING;
3107 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
3108 pbEncoded += lenBytes;
3109 *pbEncoded++ = unusedBits;
3110 if (dataBytes)
3112 BYTE mask = 0xff << unusedBits;
3114 if (dataBytes > 1)
3116 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
3117 pbEncoded += dataBytes - 1;
3119 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
3124 __EXCEPT_PAGE_FAULT
3126 SetLastError(STATUS_ACCESS_VIOLATION);
3127 ret = FALSE;
3129 __ENDTRY
3130 return ret;
3133 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
3134 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3135 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3137 BOOL ret;
3139 __TRY
3141 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
3142 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
3144 ret = TRUE;
3145 if (newBlob.cbData)
3147 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
3148 if (newBlob.pbData)
3150 DWORD i;
3152 for (i = 0; i < newBlob.cbData; i++)
3153 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
3155 else
3156 ret = FALSE;
3158 if (ret)
3159 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
3160 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3161 CryptMemFree(newBlob.pbData);
3163 __EXCEPT_PAGE_FAULT
3165 SetLastError(STATUS_ACCESS_VIOLATION);
3166 ret = FALSE;
3168 __ENDTRY
3169 return ret;
3172 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
3173 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3174 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3176 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
3178 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
3179 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3182 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
3183 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3184 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3186 BOOL ret;
3188 __TRY
3190 DWORD significantBytes, lenBytes, bytesNeeded;
3191 BYTE padByte = 0;
3192 BOOL pad = FALSE;
3193 const CRYPT_INTEGER_BLOB *blob =
3194 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
3196 significantBytes = blob->cbData;
3197 if (significantBytes)
3199 if (blob->pbData[significantBytes - 1] & 0x80)
3201 /* negative, lop off leading (little-endian) 0xffs */
3202 for (; significantBytes > 0 &&
3203 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
3205 if (blob->pbData[significantBytes - 1] < 0x80)
3207 padByte = 0xff;
3208 pad = TRUE;
3211 else
3213 /* positive, lop off leading (little-endian) zeroes */
3214 for (; significantBytes > 0 &&
3215 !blob->pbData[significantBytes - 1]; significantBytes--)
3217 if (significantBytes == 0)
3218 significantBytes = 1;
3219 if (blob->pbData[significantBytes - 1] > 0x7f)
3221 padByte = 0;
3222 pad = TRUE;
3226 if (pad)
3227 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3228 else
3229 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3230 bytesNeeded = 1 + lenBytes + significantBytes;
3231 if (pad)
3232 bytesNeeded++;
3233 if (!pbEncoded)
3235 *pcbEncoded = bytesNeeded;
3236 ret = TRUE;
3238 else
3240 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3241 pcbEncoded, bytesNeeded)))
3243 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3244 pbEncoded = *(BYTE **)pbEncoded;
3245 *pbEncoded++ = ASN_INTEGER;
3246 if (pad)
3248 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3249 pbEncoded += lenBytes;
3250 *pbEncoded++ = padByte;
3252 else
3254 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3255 pbEncoded += lenBytes;
3257 for (; significantBytes > 0; significantBytes--)
3258 *(pbEncoded++) = blob->pbData[significantBytes - 1];
3262 __EXCEPT_PAGE_FAULT
3264 SetLastError(STATUS_ACCESS_VIOLATION);
3265 ret = FALSE;
3267 __ENDTRY
3268 return ret;
3271 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
3272 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3273 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3275 BOOL ret;
3277 __TRY
3279 DWORD significantBytes, lenBytes, bytesNeeded;
3280 BOOL pad = FALSE;
3281 const CRYPT_INTEGER_BLOB *blob =
3282 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
3284 significantBytes = blob->cbData;
3285 if (significantBytes)
3287 /* positive, lop off leading (little-endian) zeroes */
3288 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
3289 significantBytes--)
3291 if (significantBytes == 0)
3292 significantBytes = 1;
3293 if (blob->pbData[significantBytes - 1] > 0x7f)
3294 pad = TRUE;
3296 if (pad)
3297 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3298 else
3299 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3300 bytesNeeded = 1 + lenBytes + significantBytes;
3301 if (pad)
3302 bytesNeeded++;
3303 if (!pbEncoded)
3305 *pcbEncoded = bytesNeeded;
3306 ret = TRUE;
3308 else
3310 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3311 pcbEncoded, bytesNeeded)))
3313 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3314 pbEncoded = *(BYTE **)pbEncoded;
3315 *pbEncoded++ = ASN_INTEGER;
3316 if (pad)
3318 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3319 pbEncoded += lenBytes;
3320 *pbEncoded++ = 0;
3322 else
3324 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3325 pbEncoded += lenBytes;
3327 for (; significantBytes > 0; significantBytes--)
3328 *(pbEncoded++) = blob->pbData[significantBytes - 1];
3332 __EXCEPT_PAGE_FAULT
3334 SetLastError(STATUS_ACCESS_VIOLATION);
3335 ret = FALSE;
3337 __ENDTRY
3338 return ret;
3341 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
3342 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3343 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3345 CRYPT_INTEGER_BLOB blob;
3346 BOOL ret;
3348 /* Encode as an unsigned integer, then change the tag to enumerated */
3349 blob.cbData = sizeof(DWORD);
3350 blob.pbData = (BYTE *)pvStructInfo;
3351 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
3352 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3353 if (ret && pbEncoded)
3355 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3356 pbEncoded = *(BYTE **)pbEncoded;
3357 pbEncoded[0] = ASN_ENUMERATED;
3359 return ret;
3362 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
3363 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3364 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3366 BOOL ret;
3368 __TRY
3370 SYSTEMTIME sysTime;
3371 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
3372 * temporary buffer because the output buffer is not NULL-terminated.
3374 char buf[16];
3375 static const DWORD bytesNeeded = sizeof(buf) - 1;
3377 if (!pbEncoded)
3379 *pcbEncoded = bytesNeeded;
3380 ret = TRUE;
3382 else
3384 /* Sanity check the year, this is a two-digit year format */
3385 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
3386 &sysTime);
3387 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
3389 SetLastError(CRYPT_E_BAD_ENCODE);
3390 ret = FALSE;
3392 if (ret)
3394 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3395 pbEncoded, pcbEncoded, bytesNeeded)))
3397 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3398 pbEncoded = *(BYTE **)pbEncoded;
3399 buf[0] = ASN_UTCTIME;
3400 buf[1] = bytesNeeded - 2;
3401 snprintf(buf + 2, sizeof(buf) - 2,
3402 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
3403 sysTime.wYear - 2000 : sysTime.wYear - 1900,
3404 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3405 sysTime.wMinute, sysTime.wSecond);
3406 memcpy(pbEncoded, buf, bytesNeeded);
3411 __EXCEPT_PAGE_FAULT
3413 SetLastError(STATUS_ACCESS_VIOLATION);
3414 ret = FALSE;
3416 __ENDTRY
3417 return ret;
3420 static BOOL CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
3421 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3422 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3424 BOOL ret;
3426 __TRY
3428 SYSTEMTIME sysTime;
3429 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
3430 * temporary buffer because the output buffer is not NULL-terminated.
3432 char buf[18];
3433 static const DWORD bytesNeeded = sizeof(buf) - 1;
3435 if (!pbEncoded)
3437 *pcbEncoded = bytesNeeded;
3438 ret = TRUE;
3440 else
3442 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
3443 &sysTime);
3444 if (ret)
3445 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3446 pcbEncoded, bytesNeeded);
3447 if (ret)
3449 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3450 pbEncoded = *(BYTE **)pbEncoded;
3451 buf[0] = ASN_GENERALTIME;
3452 buf[1] = bytesNeeded - 2;
3453 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
3454 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3455 sysTime.wMinute, sysTime.wSecond);
3456 memcpy(pbEncoded, buf, bytesNeeded);
3460 __EXCEPT_PAGE_FAULT
3462 SetLastError(STATUS_ACCESS_VIOLATION);
3463 ret = FALSE;
3465 __ENDTRY
3466 return ret;
3469 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
3470 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3471 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3473 BOOL ret;
3475 __TRY
3477 SYSTEMTIME sysTime;
3479 /* Check the year, if it's in the UTCTime range call that encode func */
3480 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
3481 return FALSE;
3482 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
3483 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
3484 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3485 else
3486 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
3487 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
3488 pcbEncoded);
3490 __EXCEPT_PAGE_FAULT
3492 SetLastError(STATUS_ACCESS_VIOLATION);
3493 ret = FALSE;
3495 __ENDTRY
3496 return ret;
3499 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
3500 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3501 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3503 BOOL ret;
3505 __TRY
3507 DWORD bytesNeeded, dataLen, lenBytes, i;
3508 const CRYPT_SEQUENCE_OF_ANY *seq =
3509 (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3511 for (i = 0, dataLen = 0; i < seq->cValue; i++)
3512 dataLen += seq->rgValue[i].cbData;
3513 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3514 bytesNeeded = 1 + lenBytes + dataLen;
3515 if (!pbEncoded)
3517 *pcbEncoded = bytesNeeded;
3518 ret = TRUE;
3520 else
3522 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3523 pcbEncoded, bytesNeeded)))
3525 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3526 pbEncoded = *(BYTE **)pbEncoded;
3527 *pbEncoded++ = ASN_SEQUENCEOF;
3528 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
3529 pbEncoded += lenBytes;
3530 for (i = 0; i < seq->cValue; i++)
3532 memcpy(pbEncoded, seq->rgValue[i].pbData,
3533 seq->rgValue[i].cbData);
3534 pbEncoded += seq->rgValue[i].cbData;
3539 __EXCEPT_PAGE_FAULT
3541 SetLastError(STATUS_ACCESS_VIOLATION);
3542 ret = FALSE;
3544 __ENDTRY
3545 return ret;
3548 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
3549 BYTE *pbEncoded, DWORD *pcbEncoded)
3551 BOOL ret = TRUE;
3552 struct AsnEncodeSequenceItem items[3] = { { 0 } };
3553 struct AsnConstructedItem constructed = { 0 };
3554 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
3555 DWORD cItem = 0, cSwapped = 0;
3557 switch (distPoint->DistPointName.dwDistPointNameChoice)
3559 case CRL_DIST_POINT_NO_NAME:
3560 /* do nothing */
3561 break;
3562 case CRL_DIST_POINT_FULL_NAME:
3563 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3564 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
3565 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3566 constructed.tag = 0;
3567 constructed.pvStructInfo = &swapped[cSwapped];
3568 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3569 items[cItem].pvStructInfo = &constructed;
3570 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3571 cSwapped++;
3572 cItem++;
3573 break;
3574 case CRL_DIST_POINT_ISSUER_RDN_NAME:
3575 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3576 ret = FALSE;
3577 break;
3578 default:
3579 ret = FALSE;
3581 if (ret && distPoint->ReasonFlags.cbData)
3583 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3584 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
3585 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3586 items[cItem].pvStructInfo = &swapped[cSwapped];
3587 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3588 cSwapped++;
3589 cItem++;
3591 if (ret && distPoint->CRLIssuer.cAltEntry)
3593 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
3594 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
3595 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3596 items[cItem].pvStructInfo = &swapped[cSwapped];
3597 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3598 cSwapped++;
3599 cItem++;
3601 if (ret)
3602 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
3603 pbEncoded, pcbEncoded);
3604 return ret;
3607 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
3608 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3609 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3611 BOOL ret;
3613 __TRY
3615 const CRL_DIST_POINTS_INFO *info =
3616 (const CRL_DIST_POINTS_INFO *)pvStructInfo;
3618 if (!info->cDistPoint)
3620 SetLastError(E_INVALIDARG);
3621 ret = FALSE;
3623 else
3625 DWORD bytesNeeded, dataLen, lenBytes, i;
3627 ret = TRUE;
3628 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
3630 DWORD len;
3632 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
3633 &len);
3634 if (ret)
3635 dataLen += len;
3636 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
3638 /* Have to propagate index of failing character */
3639 *pcbEncoded = len;
3642 if (ret)
3644 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3645 bytesNeeded = 1 + lenBytes + dataLen;
3646 if (!pbEncoded)
3648 *pcbEncoded = bytesNeeded;
3649 ret = TRUE;
3651 else
3653 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3654 pbEncoded, pcbEncoded, bytesNeeded)))
3656 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3657 pbEncoded = *(BYTE **)pbEncoded;
3658 *pbEncoded++ = ASN_SEQUENCEOF;
3659 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
3660 pbEncoded += lenBytes;
3661 for (i = 0; ret && i < info->cDistPoint; i++)
3663 DWORD len = dataLen;
3665 ret = CRYPT_AsnEncodeDistPoint(
3666 &info->rgDistPoint[i], pbEncoded, &len);
3667 if (ret)
3669 pbEncoded += len;
3670 dataLen -= len;
3678 __EXCEPT_PAGE_FAULT
3680 SetLastError(STATUS_ACCESS_VIOLATION);
3681 ret = FALSE;
3683 __ENDTRY
3684 return ret;
3687 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3688 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3689 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3691 BOOL ret;
3693 __TRY
3695 const CERT_ENHKEY_USAGE *usage =
3696 (const CERT_ENHKEY_USAGE *)pvStructInfo;
3697 DWORD bytesNeeded = 0, lenBytes, size, i;
3699 ret = TRUE;
3700 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3702 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3703 usage->rgpszUsageIdentifier[i],
3704 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
3705 if (ret)
3706 bytesNeeded += size;
3708 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3709 bytesNeeded += 1 + lenBytes;
3710 if (ret)
3712 if (!pbEncoded)
3713 *pcbEncoded = bytesNeeded;
3714 else
3716 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3717 pbEncoded, pcbEncoded, bytesNeeded)))
3719 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3720 pbEncoded = *(BYTE **)pbEncoded;
3721 *pbEncoded++ = ASN_SEQUENCEOF;
3722 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
3723 &lenBytes);
3724 pbEncoded += lenBytes;
3725 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3727 size = bytesNeeded;
3728 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3729 usage->rgpszUsageIdentifier[i],
3730 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
3731 &size);
3732 if (ret)
3734 pbEncoded += size;
3735 bytesNeeded -= size;
3742 __EXCEPT_PAGE_FAULT
3744 SetLastError(STATUS_ACCESS_VIOLATION);
3745 ret = FALSE;
3747 __ENDTRY
3748 return ret;
3751 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
3752 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3753 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3755 BOOL ret;
3757 __TRY
3759 const CRL_ISSUING_DIST_POINT *point =
3760 (const CRL_ISSUING_DIST_POINT *)pvStructInfo;
3761 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3762 struct AsnConstructedItem constructed = { 0 };
3763 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3764 DWORD cItem = 0, cSwapped = 0;
3766 ret = TRUE;
3767 switch (point->DistPointName.dwDistPointNameChoice)
3769 case CRL_DIST_POINT_NO_NAME:
3770 /* do nothing */
3771 break;
3772 case CRL_DIST_POINT_FULL_NAME:
3773 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3774 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3775 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3776 constructed.tag = 0;
3777 constructed.pvStructInfo = &swapped[cSwapped];
3778 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3779 items[cItem].pvStructInfo = &constructed;
3780 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3781 cSwapped++;
3782 cItem++;
3783 break;
3784 default:
3785 SetLastError(E_INVALIDARG);
3786 ret = FALSE;
3788 if (ret && point->fOnlyContainsUserCerts)
3790 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3791 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3792 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3793 items[cItem].pvStructInfo = &swapped[cSwapped];
3794 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3795 cSwapped++;
3796 cItem++;
3798 if (ret && point->fOnlyContainsCACerts)
3800 swapped[cSwapped].tag = ASN_CONTEXT | 2;
3801 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3802 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3803 items[cItem].pvStructInfo = &swapped[cSwapped];
3804 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3805 cSwapped++;
3806 cItem++;
3808 if (ret && point->OnlySomeReasonFlags.cbData)
3810 swapped[cSwapped].tag = ASN_CONTEXT | 3;
3811 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3812 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3813 items[cItem].pvStructInfo = &swapped[cSwapped];
3814 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3815 cSwapped++;
3816 cItem++;
3818 if (ret && point->fIndirectCRL)
3820 swapped[cSwapped].tag = ASN_CONTEXT | 4;
3821 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
3822 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3823 items[cItem].pvStructInfo = &swapped[cSwapped];
3824 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3825 cSwapped++;
3826 cItem++;
3828 if (ret)
3829 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3830 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3832 __EXCEPT_PAGE_FAULT
3834 SetLastError(STATUS_ACCESS_VIOLATION);
3835 ret = FALSE;
3837 __ENDTRY
3838 return ret;
3841 static BOOL CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType,
3842 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3843 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3845 BOOL ret;
3846 const CERT_GENERAL_SUBTREE *subtree =
3847 (const CERT_GENERAL_SUBTREE *)pvStructInfo;
3848 struct AsnEncodeSequenceItem items[3] = {
3849 { &subtree->Base, CRYPT_AsnEncodeAltNameEntry, 0 },
3850 { 0 }
3852 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3853 DWORD cItem = 1, cSwapped = 0;
3855 if (subtree->dwMinimum)
3857 swapped[cSwapped].tag = ASN_CONTEXT | 0;
3858 swapped[cSwapped].pvStructInfo = &subtree->dwMinimum;
3859 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3860 items[cItem].pvStructInfo = &swapped[cSwapped];
3861 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3862 cSwapped++;
3863 cItem++;
3865 if (subtree->fMaximum)
3867 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3868 swapped[cSwapped].pvStructInfo = &subtree->dwMaximum;
3869 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3870 items[cItem].pvStructInfo = &swapped[cSwapped];
3871 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3872 cSwapped++;
3873 cItem++;
3875 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags,
3876 pEncodePara, pbEncoded, pcbEncoded);
3877 return ret;
3880 static BOOL WINAPI CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType,
3881 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3882 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3884 BOOL ret = FALSE;
3885 CRYPT_BLOB_ARRAY permitted = { 0, NULL }, excluded = { 0, NULL };
3887 TRACE("%p\n", pvStructInfo);
3889 __TRY
3891 const CERT_NAME_CONSTRAINTS_INFO *constraints =
3892 (const CERT_NAME_CONSTRAINTS_INFO *)pvStructInfo;
3893 struct AsnEncodeSequenceItem items[2] = { { 0 } };
3894 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3895 DWORD i, cItem = 0, cSwapped = 0;
3897 ret = TRUE;
3898 if (constraints->cPermittedSubtree)
3900 permitted.rgBlob = CryptMemAlloc(
3901 constraints->cPermittedSubtree * sizeof(CRYPT_DER_BLOB));
3902 if (permitted.rgBlob)
3904 permitted.cBlob = constraints->cPermittedSubtree;
3905 memset(permitted.rgBlob, 0,
3906 permitted.cBlob * sizeof(CRYPT_DER_BLOB));
3907 for (i = 0; ret && i < permitted.cBlob; i++)
3908 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3909 NULL, &constraints->rgPermittedSubtree[i],
3910 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3911 (BYTE *)&permitted.rgBlob[i].pbData,
3912 &permitted.rgBlob[i].cbData);
3913 if (ret)
3915 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3916 swapped[cSwapped].pvStructInfo = &permitted;
3917 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3918 items[cItem].pvStructInfo = &swapped[cSwapped];
3919 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3920 cSwapped++;
3921 cItem++;
3924 else
3925 ret = FALSE;
3927 if (constraints->cExcludedSubtree)
3929 excluded.rgBlob = CryptMemAlloc(
3930 constraints->cExcludedSubtree * sizeof(CRYPT_DER_BLOB));
3931 if (excluded.rgBlob)
3933 excluded.cBlob = constraints->cExcludedSubtree;
3934 memset(excluded.rgBlob, 0,
3935 excluded.cBlob * sizeof(CRYPT_DER_BLOB));
3936 for (i = 0; ret && i < excluded.cBlob; i++)
3937 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3938 NULL, &constraints->rgExcludedSubtree[i],
3939 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3940 (BYTE *)&excluded.rgBlob[i].pbData,
3941 &excluded.rgBlob[i].cbData);
3942 if (ret)
3944 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
3945 swapped[cSwapped].pvStructInfo = &excluded;
3946 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3947 items[cItem].pvStructInfo = &swapped[cSwapped];
3948 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3949 cSwapped++;
3950 cItem++;
3953 else
3954 ret = FALSE;
3956 if (ret)
3957 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3958 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3959 for (i = 0; i < permitted.cBlob; i++)
3960 LocalFree(permitted.rgBlob[i].pbData);
3961 for (i = 0; i < excluded.cBlob; i++)
3962 LocalFree(excluded.rgBlob[i].pbData);
3964 __EXCEPT_PAGE_FAULT
3966 SetLastError(STATUS_ACCESS_VIOLATION);
3968 __ENDTRY
3969 CryptMemFree(permitted.rgBlob);
3970 CryptMemFree(excluded.rgBlob);
3971 TRACE("returning %d\n", ret);
3972 return ret;
3975 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
3976 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3977 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3978 DWORD *pcbEncoded)
3980 BOOL ret;
3981 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3982 (const CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3983 struct AsnEncodeSequenceItem items[] = {
3984 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
3985 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
3988 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3989 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3990 pcbEncoded);
3991 return ret;
3994 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
3995 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3996 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3998 BOOL ret = FALSE;
4000 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
4002 SetLastError(E_INVALIDARG);
4003 return FALSE;
4006 __TRY
4008 const CMSG_SIGNER_INFO *info = (const CMSG_SIGNER_INFO *)pvStructInfo;
4010 if (!info->Issuer.cbData)
4011 SetLastError(E_INVALIDARG);
4012 else
4014 struct AsnEncodeSequenceItem items[7] = {
4015 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4016 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
4017 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
4018 0 },
4020 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4021 DWORD cItem = 3, cSwapped = 0;
4023 if (info->AuthAttrs.cAttr)
4025 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4026 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
4027 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4028 items[cItem].pvStructInfo = &swapped[cSwapped];
4029 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4030 cSwapped++;
4031 cItem++;
4033 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
4034 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4035 cItem++;
4036 items[cItem].pvStructInfo = &info->EncryptedHash;
4037 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
4038 cItem++;
4039 if (info->UnauthAttrs.cAttr)
4041 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4042 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
4043 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4044 items[cItem].pvStructInfo = &swapped[cSwapped];
4045 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4046 cSwapped++;
4047 cItem++;
4049 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4050 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4053 __EXCEPT_PAGE_FAULT
4055 SetLastError(STATUS_ACCESS_VIOLATION);
4057 __ENDTRY
4058 return ret;
4061 static BOOL WINAPI CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType,
4062 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4063 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4065 BOOL ret = FALSE;
4067 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
4069 SetLastError(E_INVALIDARG);
4070 return FALSE;
4073 __TRY
4075 const CMSG_CMS_SIGNER_INFO *info = (const CMSG_CMS_SIGNER_INFO *)pvStructInfo;
4077 if (info->SignerId.dwIdChoice != CERT_ID_ISSUER_SERIAL_NUMBER &&
4078 info->SignerId.dwIdChoice != CERT_ID_KEY_IDENTIFIER)
4079 SetLastError(E_INVALIDARG);
4080 else if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER &&
4081 !info->SignerId.u.IssuerSerialNumber.Issuer.cbData)
4082 SetLastError(E_INVALIDARG);
4083 else
4085 struct AsnEncodeSequenceItem items[7] = {
4086 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4088 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
4089 DWORD cItem = 1, cSwapped = 0;
4091 if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
4093 items[cItem].pvStructInfo =
4094 &info->SignerId.u.IssuerSerialNumber.Issuer;
4095 items[cItem].encodeFunc =
4096 CRYPT_AsnEncodeIssuerSerialNumber;
4097 cItem++;
4099 else
4101 swapped[cSwapped].tag = ASN_CONTEXT | 0;
4102 swapped[cSwapped].pvStructInfo = &info->SignerId.u.KeyId;
4103 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
4104 items[cItem].pvStructInfo = &swapped[cSwapped];
4105 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4106 cSwapped++;
4107 cItem++;
4109 items[cItem].pvStructInfo = &info->HashAlgorithm;
4110 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4111 cItem++;
4112 if (info->AuthAttrs.cAttr)
4114 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4115 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
4116 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4117 items[cItem].pvStructInfo = &swapped[cSwapped];
4118 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4119 cSwapped++;
4120 cItem++;
4122 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
4123 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4124 cItem++;
4125 items[cItem].pvStructInfo = &info->EncryptedHash;
4126 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
4127 cItem++;
4128 if (info->UnauthAttrs.cAttr)
4130 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4131 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
4132 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4133 items[cItem].pvStructInfo = &swapped[cSwapped];
4134 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4135 cSwapped++;
4136 cItem++;
4138 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4139 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4142 __EXCEPT_PAGE_FAULT
4144 SetLastError(STATUS_ACCESS_VIOLATION);
4146 __ENDTRY
4147 return ret;
4150 BOOL CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
4151 DWORD *pcbData)
4153 struct AsnEncodeSequenceItem items[7] = {
4154 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
4156 struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 };
4157 struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 };
4158 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4159 DWORD cItem = 1, cSwapped = 0;
4160 BOOL ret = TRUE;
4162 if (signedInfo->cSignerInfo)
4164 digestAlgorithmsSet.cItems = signedInfo->cSignerInfo;
4165 digestAlgorithmsSet.items = signedInfo->rgSignerInfo;
4166 digestAlgorithmsSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
4167 digestAlgorithmsSet.itemOffset =
4168 offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm);
4169 digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4170 items[cItem].pvStructInfo = &digestAlgorithmsSet;
4171 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4172 cItem++;
4174 items[cItem].pvStructInfo = &signedInfo->content;
4175 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal;
4176 cItem++;
4177 if (signedInfo->cCertEncoded)
4179 certSet.cItems = signedInfo->cCertEncoded;
4180 certSet.items = signedInfo->rgCertEncoded;
4181 certSet.itemSize = sizeof(CERT_BLOB);
4182 certSet.itemOffset = 0;
4183 certSet.encode = CRYPT_CopyEncodedBlob;
4184 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0;
4185 swapped[cSwapped].pvStructInfo = &certSet;
4186 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4187 items[cItem].pvStructInfo = &swapped[cSwapped];
4188 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4189 cSwapped++;
4190 cItem++;
4192 if (signedInfo->cCrlEncoded)
4194 crlSet.cItems = signedInfo->cCrlEncoded;
4195 crlSet.items = signedInfo->rgCrlEncoded;
4196 crlSet.itemSize = sizeof(CRL_BLOB);
4197 crlSet.itemOffset = 0;
4198 crlSet.encode = CRYPT_CopyEncodedBlob;
4199 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
4200 swapped[cSwapped].pvStructInfo = &crlSet;
4201 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4202 items[cItem].pvStructInfo = &swapped[cSwapped];
4203 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4204 cSwapped++;
4205 cItem++;
4207 if (ret && signedInfo->cSignerInfo)
4209 signerSet.cItems = signedInfo->cSignerInfo;
4210 signerSet.items = signedInfo->rgSignerInfo;
4211 signerSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
4212 signerSet.itemOffset = 0;
4213 signerSet.encode = CRYPT_AsnEncodeCMSSignerInfo;
4214 items[cItem].pvStructInfo = &signerSet;
4215 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4216 cItem++;
4218 if (ret)
4219 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
4220 items, cItem, 0, NULL, pvData, pcbData);
4222 return ret;
4225 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
4226 LPCSTR lpszStructType)
4228 CryptEncodeObjectExFunc encodeFunc = NULL;
4230 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4231 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4233 SetLastError(ERROR_FILE_NOT_FOUND);
4234 return NULL;
4237 if (!HIWORD(lpszStructType))
4239 switch (LOWORD(lpszStructType))
4241 case LOWORD(X509_CERT):
4242 encodeFunc = CRYPT_AsnEncodeCert;
4243 break;
4244 case LOWORD(X509_CERT_TO_BE_SIGNED):
4245 encodeFunc = CRYPT_AsnEncodeCertInfo;
4246 break;
4247 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
4248 encodeFunc = CRYPT_AsnEncodeCRLInfo;
4249 break;
4250 case LOWORD(X509_EXTENSIONS):
4251 encodeFunc = CRYPT_AsnEncodeExtensions;
4252 break;
4253 case LOWORD(X509_NAME_VALUE):
4254 encodeFunc = CRYPT_AsnEncodeNameValue;
4255 break;
4256 case LOWORD(X509_NAME):
4257 encodeFunc = CRYPT_AsnEncodeName;
4258 break;
4259 case LOWORD(X509_PUBLIC_KEY_INFO):
4260 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
4261 break;
4262 case LOWORD(X509_AUTHORITY_KEY_ID):
4263 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
4264 break;
4265 case LOWORD(X509_ALTERNATE_NAME):
4266 encodeFunc = CRYPT_AsnEncodeAltName;
4267 break;
4268 case LOWORD(X509_BASIC_CONSTRAINTS):
4269 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
4270 break;
4271 case LOWORD(X509_BASIC_CONSTRAINTS2):
4272 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
4273 break;
4274 case LOWORD(X509_CERT_POLICIES):
4275 encodeFunc = CRYPT_AsnEncodeCertPolicies;
4276 break;
4277 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
4278 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
4279 break;
4280 case LOWORD(X509_UNICODE_NAME):
4281 encodeFunc = CRYPT_AsnEncodeUnicodeName;
4282 break;
4283 case LOWORD(PKCS_CONTENT_INFO):
4284 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
4285 break;
4286 case LOWORD(PKCS_ATTRIBUTE):
4287 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
4288 break;
4289 case LOWORD(X509_UNICODE_NAME_VALUE):
4290 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
4291 break;
4292 case LOWORD(X509_OCTET_STRING):
4293 encodeFunc = CRYPT_AsnEncodeOctets;
4294 break;
4295 case LOWORD(X509_BITS):
4296 case LOWORD(X509_KEY_USAGE):
4297 encodeFunc = CRYPT_AsnEncodeBits;
4298 break;
4299 case LOWORD(X509_INTEGER):
4300 encodeFunc = CRYPT_AsnEncodeInt;
4301 break;
4302 case LOWORD(X509_MULTI_BYTE_INTEGER):
4303 encodeFunc = CRYPT_AsnEncodeInteger;
4304 break;
4305 case LOWORD(X509_MULTI_BYTE_UINT):
4306 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
4307 break;
4308 case LOWORD(X509_ENUMERATED):
4309 encodeFunc = CRYPT_AsnEncodeEnumerated;
4310 break;
4311 case LOWORD(X509_CHOICE_OF_TIME):
4312 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
4313 break;
4314 case LOWORD(X509_AUTHORITY_KEY_ID2):
4315 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
4316 break;
4317 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
4318 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
4319 break;
4320 case LOWORD(X509_SEQUENCE_OF_ANY):
4321 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
4322 break;
4323 case LOWORD(PKCS_UTC_TIME):
4324 encodeFunc = CRYPT_AsnEncodeUtcTime;
4325 break;
4326 case LOWORD(X509_CRL_DIST_POINTS):
4327 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
4328 break;
4329 case LOWORD(X509_ENHANCED_KEY_USAGE):
4330 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
4331 break;
4332 case LOWORD(PKCS_CTL):
4333 encodeFunc = CRYPT_AsnEncodeCTL;
4334 break;
4335 case LOWORD(PKCS_SMIME_CAPABILITIES):
4336 encodeFunc = CRYPT_AsnEncodeSMIMECapabilities;
4337 break;
4338 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
4339 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
4340 break;
4341 case LOWORD(PKCS_ATTRIBUTES):
4342 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4343 break;
4344 case LOWORD(X509_ISSUING_DIST_POINT):
4345 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
4346 break;
4347 case LOWORD(X509_NAME_CONSTRAINTS):
4348 encodeFunc = CRYPT_AsnEncodeNameConstraints;
4349 break;
4350 case LOWORD(PKCS7_SIGNER_INFO):
4351 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
4352 break;
4353 case LOWORD(CMS_SIGNER_INFO):
4354 encodeFunc = CRYPT_AsnEncodeCMSSignerInfo;
4355 break;
4358 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4359 encodeFunc = CRYPT_AsnEncodeExtensions;
4360 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4361 encodeFunc = CRYPT_AsnEncodeUtcTime;
4362 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
4363 encodeFunc = CRYPT_AsnEncodeUtcTime;
4364 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4365 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
4366 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4367 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
4368 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4369 encodeFunc = CRYPT_AsnEncodeEnumerated;
4370 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4371 encodeFunc = CRYPT_AsnEncodeBits;
4372 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4373 encodeFunc = CRYPT_AsnEncodeOctets;
4374 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4375 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
4376 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4377 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
4378 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4379 encodeFunc = CRYPT_AsnEncodeAltName;
4380 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4381 encodeFunc = CRYPT_AsnEncodeAltName;
4382 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4383 encodeFunc = CRYPT_AsnEncodeAltName;
4384 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4385 encodeFunc = CRYPT_AsnEncodeAltName;
4386 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4387 encodeFunc = CRYPT_AsnEncodeAltName;
4388 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4389 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
4390 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
4391 encodeFunc = CRYPT_AsnEncodeCertPolicies;
4392 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4393 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
4394 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4395 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
4396 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
4397 encodeFunc = CRYPT_AsnEncodeNameConstraints;
4398 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
4399 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
4400 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
4401 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
4402 else if (!strcmp(lpszStructType, szOID_CTL))
4403 encodeFunc = CRYPT_AsnEncodeCTL;
4404 return encodeFunc;
4407 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType,
4408 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4410 static HCRYPTOIDFUNCSET set = NULL;
4411 CryptEncodeObjectFunc encodeFunc = NULL;
4413 if (!set)
4414 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
4415 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4416 (void **)&encodeFunc, hFunc);
4417 return encodeFunc;
4420 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType,
4421 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4423 static HCRYPTOIDFUNCSET set = NULL;
4424 CryptEncodeObjectExFunc encodeFunc = NULL;
4426 if (!set)
4427 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
4428 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4429 (void **)&encodeFunc, hFunc);
4430 return encodeFunc;
4433 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4434 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
4436 BOOL ret = FALSE;
4437 HCRYPTOIDFUNCADDR hFunc = NULL;
4438 CryptEncodeObjectFunc pCryptEncodeObject = NULL;
4439 CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL;
4441 TRACE_(crypt)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
4442 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
4443 pcbEncoded);
4445 if (!pbEncoded && !pcbEncoded)
4447 SetLastError(ERROR_INVALID_PARAMETER);
4448 return FALSE;
4451 if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType,
4452 lpszStructType)))
4454 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4455 debugstr_a(lpszStructType));
4456 pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType,
4457 lpszStructType, &hFunc);
4458 if (!pCryptEncodeObject)
4459 pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType,
4460 lpszStructType, &hFunc);
4462 if (pCryptEncodeObject)
4463 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4464 pvStructInfo, pbEncoded, pcbEncoded);
4465 else if (pCryptEncodeObjectEx)
4466 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
4467 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
4468 if (hFunc)
4469 CryptFreeOIDFunctionAddress(hFunc, 0);
4470 TRACE_(crypt)("returning %d\n", ret);
4471 return ret;
4474 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4475 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
4476 void *pvEncoded, DWORD *pcbEncoded)
4478 BOOL ret = FALSE;
4479 HCRYPTOIDFUNCADDR hFunc = NULL;
4480 CryptEncodeObjectExFunc encodeFunc = NULL;
4482 TRACE_(crypt)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
4483 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
4484 pvEncoded, pcbEncoded);
4486 if (!pvEncoded && !pcbEncoded)
4488 SetLastError(ERROR_INVALID_PARAMETER);
4489 return FALSE;
4492 SetLastError(NOERROR);
4493 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
4494 *(BYTE **)pvEncoded = NULL;
4495 encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType);
4496 if (!encodeFunc)
4498 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4499 debugstr_a(lpszStructType));
4500 encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType,
4501 &hFunc);
4503 if (encodeFunc)
4504 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
4505 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
4506 else
4508 CryptEncodeObjectFunc pCryptEncodeObject =
4509 CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4511 if (pCryptEncodeObject)
4513 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
4515 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4516 pvStructInfo, NULL, pcbEncoded);
4517 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
4518 pvEncoded, pcbEncoded, *pcbEncoded)))
4519 ret = pCryptEncodeObject(dwCertEncodingType,
4520 lpszStructType, pvStructInfo, *(BYTE **)pvEncoded,
4521 pcbEncoded);
4523 else
4524 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4525 pvStructInfo, pvEncoded, pcbEncoded);
4528 if (hFunc)
4529 CryptFreeOIDFunctionAddress(hFunc, 0);
4530 TRACE_(crypt)("returning %d\n", ret);
4531 return ret;
4534 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
4535 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4537 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
4538 NULL, 0, NULL, pInfo, pcbInfo);
4541 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
4542 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
4543 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4545 BOOL ret;
4546 HCRYPTKEY key;
4547 static CHAR oid[] = szOID_RSA_RSA;
4549 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
4550 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
4551 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
4553 if (!pszPublicKeyObjId)
4554 pszPublicKeyObjId = oid;
4555 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
4557 DWORD keySize = 0;
4559 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
4560 if (ret)
4562 LPBYTE pubKey = CryptMemAlloc(keySize);
4564 if (pubKey)
4566 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
4567 &keySize);
4568 if (ret)
4570 DWORD encodedLen = 0;
4572 ret = CryptEncodeObject(dwCertEncodingType,
4573 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
4574 if (ret)
4576 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
4577 strlen(pszPublicKeyObjId) + 1 + encodedLen;
4579 if (!pInfo)
4580 *pcbInfo = sizeNeeded;
4581 else if (*pcbInfo < sizeNeeded)
4583 SetLastError(ERROR_MORE_DATA);
4584 *pcbInfo = sizeNeeded;
4585 ret = FALSE;
4587 else
4589 pInfo->Algorithm.pszObjId = (char *)pInfo +
4590 sizeof(CERT_PUBLIC_KEY_INFO);
4591 lstrcpyA(pInfo->Algorithm.pszObjId,
4592 pszPublicKeyObjId);
4593 pInfo->Algorithm.Parameters.cbData = 0;
4594 pInfo->Algorithm.Parameters.pbData = NULL;
4595 pInfo->PublicKey.pbData =
4596 (BYTE *)pInfo->Algorithm.pszObjId
4597 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
4598 pInfo->PublicKey.cbData = encodedLen;
4599 pInfo->PublicKey.cUnusedBits = 0;
4600 ret = CryptEncodeObject(dwCertEncodingType,
4601 RSA_CSP_PUBLICKEYBLOB, pubKey,
4602 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
4606 CryptMemFree(pubKey);
4608 else
4609 ret = FALSE;
4611 CryptDestroyKey(key);
4613 return ret;
4616 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
4617 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
4618 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
4620 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
4621 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
4622 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4624 static HCRYPTOIDFUNCSET set = NULL;
4625 BOOL ret;
4626 ExportPublicKeyInfoExFunc exportFunc = NULL;
4627 HCRYPTOIDFUNCADDR hFunc = NULL;
4629 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
4630 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
4631 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
4633 if (!hCryptProv)
4635 SetLastError(ERROR_INVALID_PARAMETER);
4636 return FALSE;
4639 if (pszPublicKeyObjId)
4641 if (!set)
4642 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
4644 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
4645 0, (void **)&exportFunc, &hFunc);
4647 if (!exportFunc)
4648 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
4649 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
4650 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
4651 if (hFunc)
4652 CryptFreeOIDFunctionAddress(hFunc, 0);
4653 return ret;
4656 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
4657 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
4659 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
4660 0, 0, NULL, phKey);
4663 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
4664 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4665 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
4667 BOOL ret;
4668 DWORD pubKeySize = 0;
4670 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
4671 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
4673 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
4674 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
4675 if (ret)
4677 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
4679 if (pubKey)
4681 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
4682 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
4683 &pubKeySize);
4684 if (ret)
4686 if(aiKeyAlg)
4687 ((BLOBHEADER*)pubKey)->aiKeyAlg = aiKeyAlg;
4688 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
4689 phKey);
4691 CryptMemFree(pubKey);
4693 else
4694 ret = FALSE;
4696 return ret;
4699 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
4700 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4701 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
4703 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
4704 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4705 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
4707 static HCRYPTOIDFUNCSET set = NULL;
4708 BOOL ret;
4709 ImportPublicKeyInfoExFunc importFunc = NULL;
4710 HCRYPTOIDFUNCADDR hFunc = NULL;
4712 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
4713 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
4715 if (!set)
4716 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
4717 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
4718 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
4719 if (!importFunc)
4720 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
4721 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
4722 pvAuxInfo, phKey);
4723 if (hFunc)
4724 CryptFreeOIDFunctionAddress(hFunc, 0);
4725 return ret;