dpwsockx: Implementation of SPInit
[wine/gsoc_dplay.git] / dlls / crypt32 / encode.c
blob258384c731859fd19802bd67a3b94a5297a9f426
1 /*
2 * Copyright 2005-2008 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER encoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface isn't
21 * implemented, so I implement them here.
23 * References:
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
33 #include "config.h"
34 #include "wine/port.h"
36 #include <assert.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <stdlib.h>
41 #define NONAMELESSUNION
43 #include "windef.h"
44 #include "winbase.h"
45 #include "wincrypt.h"
46 #include "snmp.h"
47 #include "wine/debug.h"
48 #include "wine/exception.h"
49 #include "wine/unicode.h"
50 #include "crypt32_private.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
53 WINE_DECLARE_DEBUG_CHANNEL(crypt);
55 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
56 BYTE *, DWORD *);
58 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
59 * The dwCertEncodingType and lpszStructType are ignored by the built-in
60 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
61 * since it must call functions in external DLLs that follow these signatures.
63 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
64 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
65 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
66 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
67 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
68 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
69 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
70 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
71 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
72 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
73 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
74 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
75 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
76 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
77 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
78 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
79 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
80 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
81 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
82 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
83 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
84 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
85 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
86 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
87 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
88 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
89 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
90 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
91 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
92 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
93 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
94 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
95 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
96 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
97 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
98 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
99 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
100 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
101 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
103 BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
104 BYTE *pbEncoded, DWORD *pcbEncoded, DWORD bytesNeeded)
106 BOOL ret = TRUE;
108 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
110 if (pEncodePara && pEncodePara->pfnAlloc)
111 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
112 else
113 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
114 if (!*(BYTE **)pbEncoded)
115 ret = FALSE;
116 else
117 *pcbEncoded = bytesNeeded;
119 else if (bytesNeeded > *pcbEncoded)
121 *pcbEncoded = bytesNeeded;
122 SetLastError(ERROR_MORE_DATA);
123 ret = FALSE;
125 else
126 *pcbEncoded = bytesNeeded;
127 return ret;
130 BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
132 DWORD bytesNeeded, significantBytes = 0;
134 if (len <= 0x7f)
135 bytesNeeded = 1;
136 else
138 DWORD temp;
140 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
141 temp <<= 8, significantBytes--)
143 bytesNeeded = significantBytes + 1;
145 if (!pbEncoded)
147 *pcbEncoded = bytesNeeded;
148 return TRUE;
150 if (*pcbEncoded < bytesNeeded)
152 SetLastError(ERROR_MORE_DATA);
153 return FALSE;
155 if (len <= 0x7f)
156 *pbEncoded = (BYTE)len;
157 else
159 DWORD i;
161 *pbEncoded++ = significantBytes | 0x80;
162 for (i = 0; i < significantBytes; i++)
164 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
165 len >>= 8;
168 *pcbEncoded = bytesNeeded;
169 return TRUE;
172 BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
173 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
174 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
176 BOOL ret;
177 DWORD i, dataLen = 0;
179 TRACE("%p, %d, %08x, %p, %p, %d\n", items, cItem, dwFlags, pEncodePara,
180 pbEncoded, *pcbEncoded);
181 for (i = 0, ret = TRUE; ret && i < cItem; i++)
183 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
184 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
185 NULL, &items[i].size);
186 /* Some functions propagate their errors through the size */
187 if (!ret)
188 *pcbEncoded = items[i].size;
189 dataLen += items[i].size;
191 if (ret)
193 DWORD lenBytes, bytesNeeded;
195 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
196 bytesNeeded = 1 + lenBytes + dataLen;
197 if (!pbEncoded)
198 *pcbEncoded = bytesNeeded;
199 else
201 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
202 pcbEncoded, bytesNeeded)))
204 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
205 pbEncoded = *(BYTE **)pbEncoded;
206 *pbEncoded++ = ASN_SEQUENCE;
207 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
208 pbEncoded += lenBytes;
209 for (i = 0; ret && i < cItem; i++)
211 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
212 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
213 NULL, pbEncoded, &items[i].size);
214 /* Some functions propagate their errors through the size */
215 if (!ret)
216 *pcbEncoded = items[i].size;
217 pbEncoded += items[i].size;
222 TRACE("returning %d (%08x)\n", ret, GetLastError());
223 return ret;
226 BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
227 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
228 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
230 BOOL ret;
231 const struct AsnConstructedItem *item = pvStructInfo;
232 DWORD len;
234 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
235 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
237 DWORD dataLen, bytesNeeded;
239 CRYPT_EncodeLen(len, NULL, &dataLen);
240 bytesNeeded = 1 + dataLen + len;
241 if (!pbEncoded)
242 *pcbEncoded = bytesNeeded;
243 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
244 pbEncoded, pcbEncoded, bytesNeeded)))
246 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
247 pbEncoded = *(BYTE **)pbEncoded;
248 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
249 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
250 pbEncoded += dataLen;
251 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
252 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
253 pbEncoded, &len);
254 if (!ret)
256 /* Some functions propagate their errors through the size */
257 *pcbEncoded = len;
261 else
263 /* Some functions propagate their errors through the size */
264 *pcbEncoded = len;
266 return ret;
269 struct AsnEncodeTagSwappedItem
271 BYTE tag;
272 const void *pvStructInfo;
273 CryptEncodeObjectExFunc encodeFunc;
276 /* Sort of a wacky hack, it encodes something using the struct
277 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
278 * given in the struct AsnEncodeTagSwappedItem.
280 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
281 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
282 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
284 BOOL ret;
285 const struct AsnEncodeTagSwappedItem *item = pvStructInfo;
287 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
288 item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
289 if (ret && pbEncoded)
290 *pbEncoded = item->tag;
291 return ret;
294 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
295 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
296 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
298 const DWORD *ver = pvStructInfo;
299 BOOL ret;
301 /* CERT_V1 is not encoded */
302 if (*ver == CERT_V1)
304 *pcbEncoded = 0;
305 ret = TRUE;
307 else
309 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
311 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
312 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
314 return ret;
317 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
318 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
319 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
321 const CRYPT_DER_BLOB *blob = pvStructInfo;
322 BOOL ret;
324 if (!pbEncoded)
326 *pcbEncoded = blob->cbData;
327 ret = TRUE;
329 else
331 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
332 pcbEncoded, blob->cbData)))
334 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
335 pbEncoded = *(BYTE **)pbEncoded;
336 if (blob->cbData)
337 memcpy(pbEncoded, blob->pbData, blob->cbData);
338 *pcbEncoded = blob->cbData;
339 ret = TRUE;
342 return ret;
345 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
346 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
347 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
349 BOOL ret;
350 /* This has two filetimes in a row, a NotBefore and a NotAfter */
351 const FILETIME *timePtr = pvStructInfo;
352 struct AsnEncodeSequenceItem items[] = {
353 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
354 { timePtr + 1, CRYPT_AsnEncodeChoiceOfTime, 0 },
357 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
358 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
359 pcbEncoded);
360 return ret;
363 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
364 * if they are empty.
366 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
367 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
368 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
369 DWORD *pcbEncoded)
371 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
372 static const BYTE asn1Null[] = { ASN_NULL, 0 };
373 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
374 (LPBYTE)asn1Null };
375 BOOL ret;
376 struct AsnEncodeSequenceItem items[2] = {
377 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
378 { NULL, CRYPT_CopyEncodedBlob, 0 },
381 if (algo->Parameters.cbData)
382 items[1].pvStructInfo = &algo->Parameters;
383 else
384 items[1].pvStructInfo = &nullBlob;
385 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
386 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
387 pcbEncoded);
388 return ret;
391 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType,
392 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
393 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
395 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
396 BOOL ret;
397 struct AsnEncodeSequenceItem items[] = {
398 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
399 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
402 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
403 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
404 pcbEncoded);
405 return ret;
408 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
409 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
410 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
412 BOOL ret;
414 __TRY
416 const CERT_PUBLIC_KEY_INFO *info = pvStructInfo;
417 struct AsnEncodeSequenceItem items[] = {
418 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
419 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
422 TRACE("Encoding public key with OID %s\n",
423 debugstr_a(info->Algorithm.pszObjId));
424 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
425 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
426 pcbEncoded);
428 __EXCEPT_PAGE_FAULT
430 SetLastError(STATUS_ACCESS_VIOLATION);
431 ret = FALSE;
433 __ENDTRY
434 return ret;
437 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
438 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
439 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
441 BOOL ret;
443 __TRY
445 const CERT_SIGNED_CONTENT_INFO *info = pvStructInfo;
446 struct AsnEncodeSequenceItem items[] = {
447 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
448 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
449 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
452 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
453 items[2].encodeFunc = CRYPT_AsnEncodeBits;
454 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
455 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
456 pcbEncoded);
458 __EXCEPT_PAGE_FAULT
460 SetLastError(STATUS_ACCESS_VIOLATION);
461 ret = FALSE;
463 __ENDTRY
464 return ret;
467 /* Like in Windows, this blithely ignores the validity of the passed-in
468 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
469 * decode properly, see CRYPT_AsnDecodeCertInfo.
471 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
472 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
473 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
475 BOOL ret;
477 __TRY
479 const CERT_INFO *info = pvStructInfo;
480 struct AsnEncodeSequenceItem items[10] = {
481 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
482 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
483 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
484 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
485 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
486 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
487 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfo, 0 },
488 { 0 }
490 struct AsnConstructedItem constructed[3] = { { 0 } };
491 DWORD cItem = 7, cConstructed = 0;
493 if (info->IssuerUniqueId.cbData)
495 constructed[cConstructed].tag = 1;
496 constructed[cConstructed].pvStructInfo = &info->IssuerUniqueId;
497 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
498 items[cItem].pvStructInfo = &constructed[cConstructed];
499 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
500 cConstructed++;
501 cItem++;
503 if (info->SubjectUniqueId.cbData)
505 constructed[cConstructed].tag = 2;
506 constructed[cConstructed].pvStructInfo = &info->SubjectUniqueId;
507 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
508 items[cItem].pvStructInfo = &constructed[cConstructed];
509 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
510 cConstructed++;
511 cItem++;
513 if (info->cExtension)
515 constructed[cConstructed].tag = 3;
516 constructed[cConstructed].pvStructInfo = &info->cExtension;
517 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
518 items[cItem].pvStructInfo = &constructed[cConstructed];
519 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
520 cConstructed++;
521 cItem++;
524 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
525 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
527 __EXCEPT_PAGE_FAULT
529 SetLastError(STATUS_ACCESS_VIOLATION);
530 ret = FALSE;
532 __ENDTRY
533 return ret;
536 static BOOL CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
537 BYTE *pbEncoded, DWORD *pcbEncoded)
539 struct AsnEncodeSequenceItem items[3] = {
540 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
541 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
542 { 0 }
544 DWORD cItem = 2;
545 BOOL ret;
547 TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded);
549 if (entry->cExtension)
551 items[cItem].pvStructInfo = &entry->cExtension;
552 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
553 cItem++;
556 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
557 pbEncoded, pcbEncoded);
559 TRACE("returning %d (%08x)\n", ret, GetLastError());
560 return ret;
563 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
564 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
565 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
567 DWORD bytesNeeded, dataLen, lenBytes, i;
568 const CRL_INFO *info = pvStructInfo;
569 const CRL_ENTRY *rgCRLEntry = info->rgCRLEntry;
570 BOOL ret = TRUE;
572 for (i = 0, dataLen = 0; ret && i < info->cCRLEntry; i++)
574 DWORD size;
576 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
577 if (ret)
578 dataLen += size;
580 if (ret)
582 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
583 bytesNeeded = 1 + lenBytes + dataLen;
584 if (!pbEncoded)
585 *pcbEncoded = bytesNeeded;
586 else
588 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
589 pcbEncoded, bytesNeeded)))
591 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
592 pbEncoded = *(BYTE **)pbEncoded;
593 *pbEncoded++ = ASN_SEQUENCEOF;
594 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
595 pbEncoded += lenBytes;
596 for (i = 0; i < info->cCRLEntry; i++)
598 DWORD size = dataLen;
600 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], pbEncoded,
601 &size);
602 pbEncoded += size;
603 dataLen -= size;
608 return ret;
611 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
612 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
613 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
615 const DWORD *ver = pvStructInfo;
616 BOOL ret;
618 /* CRL_V1 is not encoded */
619 if (*ver == CRL_V1)
621 *pcbEncoded = 0;
622 ret = TRUE;
624 else
625 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
626 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
627 return ret;
630 /* Like in Windows, this blithely ignores the validity of the passed-in
631 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
632 * decode properly, see CRYPT_AsnDecodeCRLInfo.
634 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
635 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
636 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
638 BOOL ret;
640 __TRY
642 const CRL_INFO *info = pvStructInfo;
643 struct AsnEncodeSequenceItem items[7] = {
644 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
645 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
646 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
647 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
648 { 0 }
650 struct AsnConstructedItem constructed[1] = { { 0 } };
651 DWORD cItem = 4, cConstructed = 0;
653 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
655 items[cItem].pvStructInfo = &info->NextUpdate;
656 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
657 cItem++;
659 if (info->cCRLEntry)
661 items[cItem].pvStructInfo = info;
662 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
663 cItem++;
665 if (info->cExtension)
667 constructed[cConstructed].tag = 0;
668 constructed[cConstructed].pvStructInfo = &info->cExtension;
669 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
670 items[cItem].pvStructInfo = &constructed[cConstructed];
671 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
672 cConstructed++;
673 cItem++;
676 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
677 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
679 __EXCEPT_PAGE_FAULT
681 SetLastError(STATUS_ACCESS_VIOLATION);
682 ret = FALSE;
684 __ENDTRY
685 return ret;
688 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
689 DWORD *pcbEncoded)
691 BOOL ret;
692 struct AsnEncodeSequenceItem items[3] = {
693 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
694 { NULL, NULL, 0 },
695 { NULL, NULL, 0 },
697 DWORD cItem = 1;
699 TRACE("%p, %p, %d\n", ext, pbEncoded, *pcbEncoded);
701 if (ext->fCritical)
703 items[cItem].pvStructInfo = &ext->fCritical;
704 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
705 cItem++;
707 items[cItem].pvStructInfo = &ext->Value;
708 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
709 cItem++;
711 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
712 pbEncoded, pcbEncoded);
713 TRACE("returning %d (%08x)\n", ret, GetLastError());
714 return ret;
717 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
718 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
719 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
721 BOOL ret;
723 __TRY
725 DWORD bytesNeeded, dataLen, lenBytes, i;
726 const CERT_EXTENSIONS *exts = pvStructInfo;
728 ret = TRUE;
729 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
731 DWORD size;
733 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
734 if (ret)
735 dataLen += size;
737 if (ret)
739 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
740 bytesNeeded = 1 + lenBytes + dataLen;
741 if (!pbEncoded)
742 *pcbEncoded = bytesNeeded;
743 else
745 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
746 pbEncoded, pcbEncoded, bytesNeeded)))
748 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
749 pbEncoded = *(BYTE **)pbEncoded;
750 *pbEncoded++ = ASN_SEQUENCEOF;
751 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
752 pbEncoded += lenBytes;
753 for (i = 0; i < exts->cExtension; i++)
755 DWORD size = dataLen;
757 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
758 pbEncoded, &size);
759 pbEncoded += size;
760 dataLen -= size;
766 __EXCEPT_PAGE_FAULT
768 SetLastError(STATUS_ACCESS_VIOLATION);
769 ret = FALSE;
771 __ENDTRY
772 return ret;
775 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
776 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
777 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
779 LPCSTR pszObjId = pvStructInfo;
780 DWORD bytesNeeded = 0, lenBytes;
781 BOOL ret = TRUE;
782 int firstPos = 0;
783 BYTE firstByte = 0;
785 TRACE("%s\n", debugstr_a(pszObjId));
787 if (pszObjId)
789 const char *ptr;
790 int val1, val2;
792 if (sscanf(pszObjId, "%d.%d%n", &val1, &val2, &firstPos) != 2)
794 SetLastError(CRYPT_E_ASN1_ERROR);
795 return FALSE;
797 bytesNeeded++;
798 firstByte = val1 * 40 + val2;
799 ptr = pszObjId + firstPos;
800 if (*ptr == '.')
802 ptr++;
803 firstPos++;
805 while (ret && *ptr)
807 int pos;
809 /* note I assume each component is at most 32-bits long in base 2 */
810 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
812 if (val1 >= 0x10000000)
813 bytesNeeded += 5;
814 else if (val1 >= 0x200000)
815 bytesNeeded += 4;
816 else if (val1 >= 0x4000)
817 bytesNeeded += 3;
818 else if (val1 >= 0x80)
819 bytesNeeded += 2;
820 else
821 bytesNeeded += 1;
822 ptr += pos;
823 if (*ptr == '.')
824 ptr++;
826 else
828 SetLastError(CRYPT_E_ASN1_ERROR);
829 return FALSE;
832 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
834 else
835 lenBytes = 1;
836 bytesNeeded += 1 + lenBytes;
837 if (pbEncoded)
839 if (*pcbEncoded < bytesNeeded)
841 SetLastError(ERROR_MORE_DATA);
842 ret = FALSE;
844 else
846 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
847 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
848 pbEncoded += lenBytes;
849 if (pszObjId)
851 const char *ptr;
852 int val, pos;
854 *pbEncoded++ = firstByte;
855 ptr = pszObjId + firstPos;
856 while (ret && *ptr)
858 sscanf(ptr, "%d%n", &val, &pos);
860 unsigned char outBytes[5];
861 int numBytes, i;
863 if (val >= 0x10000000)
864 numBytes = 5;
865 else if (val >= 0x200000)
866 numBytes = 4;
867 else if (val >= 0x4000)
868 numBytes = 3;
869 else if (val >= 0x80)
870 numBytes = 2;
871 else
872 numBytes = 1;
873 for (i = numBytes; i > 0; i--)
875 outBytes[i - 1] = val & 0x7f;
876 val >>= 7;
878 for (i = 0; i < numBytes - 1; i++)
879 *pbEncoded++ = outBytes[i] | 0x80;
880 *pbEncoded++ = outBytes[i];
881 ptr += pos;
882 if (*ptr == '.')
883 ptr++;
889 *pcbEncoded = bytesNeeded;
890 return ret;
893 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
894 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
895 DWORD *pcbEncoded)
897 BOOL ret = TRUE;
898 LPCSTR str = (LPCSTR)value->Value.pbData;
899 DWORD bytesNeeded, lenBytes, encodedLen;
901 encodedLen = value->Value.cbData ? value->Value.cbData : strlen(str);
902 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
903 bytesNeeded = 1 + lenBytes + encodedLen;
904 if (!pbEncoded)
905 *pcbEncoded = bytesNeeded;
906 else
908 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
909 pbEncoded, pcbEncoded, bytesNeeded)))
911 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
912 pbEncoded = *(BYTE **)pbEncoded;
913 *pbEncoded++ = tag;
914 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
915 pbEncoded += lenBytes;
916 memcpy(pbEncoded, str, encodedLen);
919 return ret;
922 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
923 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
924 DWORD *pcbEncoded)
926 BOOL ret = TRUE;
927 LPCWSTR str = (LPCWSTR)value->Value.pbData;
928 DWORD bytesNeeded, lenBytes, strLen;
930 if (value->Value.cbData)
931 strLen = value->Value.cbData / sizeof(WCHAR);
932 else if (value->Value.pbData)
933 strLen = lstrlenW(str);
934 else
935 strLen = 0;
936 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
937 bytesNeeded = 1 + lenBytes + strLen * 2;
938 if (!pbEncoded)
939 *pcbEncoded = bytesNeeded;
940 else
942 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
943 pbEncoded, pcbEncoded, bytesNeeded)))
945 DWORD i;
947 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
948 pbEncoded = *(BYTE **)pbEncoded;
949 *pbEncoded++ = ASN_BMPSTRING;
950 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
951 pbEncoded += lenBytes;
952 for (i = 0; i < strLen; i++)
954 *pbEncoded++ = (str[i] & 0xff00) >> 8;
955 *pbEncoded++ = str[i] & 0x00ff;
959 return ret;
962 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
963 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
964 DWORD *pcbEncoded)
966 BOOL ret = TRUE;
967 LPCWSTR str = (LPCWSTR)value->Value.pbData;
968 DWORD bytesNeeded, lenBytes, encodedLen, strLen;
970 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
971 strlenW(str);
972 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
973 NULL);
974 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
975 bytesNeeded = 1 + lenBytes + encodedLen;
976 if (!pbEncoded)
977 *pcbEncoded = bytesNeeded;
978 else
980 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
981 pbEncoded, pcbEncoded, bytesNeeded)))
983 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
984 pbEncoded = *(BYTE **)pbEncoded;
985 *pbEncoded++ = ASN_UTF8STRING;
986 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
987 pbEncoded += lenBytes;
988 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
989 bytesNeeded - lenBytes - 1, NULL, NULL);
992 return ret;
995 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
996 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
997 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
999 BOOL ret = TRUE;
1001 __TRY
1003 const CERT_NAME_VALUE *value = pvStructInfo;
1005 switch (value->dwValueType)
1007 case CERT_RDN_ANY_TYPE:
1008 /* explicitly disallowed */
1009 SetLastError(E_INVALIDARG);
1010 ret = FALSE;
1011 break;
1012 case CERT_RDN_ENCODED_BLOB:
1013 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
1014 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1015 break;
1016 case CERT_RDN_OCTET_STRING:
1017 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1018 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1019 break;
1020 case CERT_RDN_NUMERIC_STRING:
1021 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1022 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1023 break;
1024 case CERT_RDN_PRINTABLE_STRING:
1025 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1026 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1027 break;
1028 case CERT_RDN_TELETEX_STRING:
1029 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1030 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1031 break;
1032 case CERT_RDN_VIDEOTEX_STRING:
1033 ret = CRYPT_AsnEncodeStringCoerce(value,
1034 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1035 break;
1036 case CERT_RDN_IA5_STRING:
1037 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1038 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1039 break;
1040 case CERT_RDN_GRAPHIC_STRING:
1041 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1042 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1043 break;
1044 case CERT_RDN_VISIBLE_STRING:
1045 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1046 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1047 break;
1048 case CERT_RDN_GENERAL_STRING:
1049 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1050 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1051 break;
1052 case CERT_RDN_UNIVERSAL_STRING:
1053 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1054 SetLastError(CRYPT_E_ASN1_CHOICE);
1055 ret = FALSE;
1056 break;
1057 case CERT_RDN_BMP_STRING:
1058 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1059 pbEncoded, pcbEncoded);
1060 break;
1061 case CERT_RDN_UTF8_STRING:
1062 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1063 pbEncoded, pcbEncoded);
1064 break;
1065 default:
1066 SetLastError(CRYPT_E_ASN1_CHOICE);
1067 ret = FALSE;
1070 __EXCEPT_PAGE_FAULT
1072 SetLastError(STATUS_ACCESS_VIOLATION);
1073 ret = FALSE;
1075 __ENDTRY
1076 return ret;
1079 static BOOL CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1080 const CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1081 BYTE *pbEncoded, DWORD *pcbEncoded)
1083 DWORD bytesNeeded = 0, lenBytes, size;
1084 BOOL ret;
1086 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1087 0, NULL, NULL, &size);
1088 if (ret)
1090 bytesNeeded += size;
1091 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1092 * with dwValueType, so "cast" it to get its encoded size
1094 ret = nameValueEncodeFunc(dwCertEncodingType, NULL, &attr->dwValueType,
1095 0, NULL, NULL, &size);
1096 if (ret)
1098 bytesNeeded += size;
1099 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1100 bytesNeeded += 1 + lenBytes;
1101 if (pbEncoded)
1103 if (*pcbEncoded < bytesNeeded)
1105 SetLastError(ERROR_MORE_DATA);
1106 ret = FALSE;
1108 else
1110 *pbEncoded++ = ASN_SEQUENCE;
1111 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1112 &lenBytes);
1113 pbEncoded += lenBytes;
1114 size = bytesNeeded - 1 - lenBytes;
1115 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1116 attr->pszObjId, 0, NULL, pbEncoded, &size);
1117 if (ret)
1119 pbEncoded += size;
1120 size = bytesNeeded - 1 - lenBytes - size;
1121 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1122 &attr->dwValueType, 0, NULL, pbEncoded, &size);
1123 if (!ret)
1124 *pcbEncoded = size;
1128 if (ret)
1129 *pcbEncoded = bytesNeeded;
1131 else
1133 /* Have to propagate index of failing character */
1134 *pcbEncoded = size;
1137 return ret;
1140 static int BLOBComp(const void *l, const void *r)
1142 const CRYPT_DER_BLOB *a = l, *b = r;
1143 int ret;
1145 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1146 ret = a->cbData - b->cbData;
1147 return ret;
1150 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1152 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1153 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1154 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1156 const CRYPT_BLOB_ARRAY *set = pvStructInfo;
1157 DWORD bytesNeeded = 0, lenBytes, i;
1158 BOOL ret;
1160 for (i = 0; i < set->cBlob; i++)
1161 bytesNeeded += set->rgBlob[i].cbData;
1162 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1163 bytesNeeded += 1 + lenBytes;
1164 if (!pbEncoded)
1166 *pcbEncoded = bytesNeeded;
1167 ret = TRUE;
1169 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1170 pbEncoded, pcbEncoded, bytesNeeded)))
1172 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1173 pbEncoded = *(BYTE **)pbEncoded;
1174 qsort(set->rgBlob, set->cBlob, sizeof(CRYPT_DER_BLOB), BLOBComp);
1175 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1176 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1177 pbEncoded += lenBytes;
1178 for (i = 0; ret && i < set->cBlob; i++)
1180 memcpy(pbEncoded, set->rgBlob[i].pbData, set->rgBlob[i].cbData);
1181 pbEncoded += set->rgBlob[i].cbData;
1184 return ret;
1187 struct DERSetDescriptor
1189 DWORD cItems;
1190 const void *items;
1191 size_t itemSize;
1192 size_t itemOffset;
1193 CryptEncodeObjectExFunc encode;
1196 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,
1197 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1198 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1200 const struct DERSetDescriptor *desc = pvStructInfo;
1201 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1202 BOOL ret = TRUE;
1203 DWORD i;
1205 if (desc->cItems)
1207 setOf.rgBlob = CryptMemAlloc(desc->cItems * sizeof(CRYPT_DER_BLOB));
1208 if (!setOf.rgBlob)
1209 ret = FALSE;
1210 else
1212 setOf.cBlob = desc->cItems;
1213 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1216 for (i = 0; ret && i < setOf.cBlob; i++)
1218 ret = desc->encode(dwCertEncodingType, lpszStructType,
1219 (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
1220 0, NULL, NULL, &setOf.rgBlob[i].cbData);
1221 if (ret)
1223 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1224 if (!setOf.rgBlob[i].pbData)
1225 ret = FALSE;
1226 else
1227 ret = desc->encode(dwCertEncodingType, lpszStructType,
1228 (const BYTE *)desc->items + i * desc->itemSize +
1229 desc->itemOffset, 0, NULL, setOf.rgBlob[i].pbData,
1230 &setOf.rgBlob[i].cbData);
1232 /* Some functions propagate their errors through the size */
1233 if (!ret)
1234 *pcbEncoded = setOf.rgBlob[i].cbData;
1236 if (ret)
1238 DWORD bytesNeeded = 0, lenBytes;
1240 for (i = 0; i < setOf.cBlob; i++)
1241 bytesNeeded += setOf.rgBlob[i].cbData;
1242 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1243 bytesNeeded += 1 + lenBytes;
1244 if (!pbEncoded)
1245 *pcbEncoded = bytesNeeded;
1246 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1247 pbEncoded, pcbEncoded, bytesNeeded)))
1249 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1250 pbEncoded = *(BYTE **)pbEncoded;
1251 qsort(setOf.rgBlob, setOf.cBlob, sizeof(CRYPT_DER_BLOB),
1252 BLOBComp);
1253 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1254 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1255 pbEncoded += lenBytes;
1256 for (i = 0; i < setOf.cBlob; i++)
1258 memcpy(pbEncoded, setOf.rgBlob[i].pbData,
1259 setOf.rgBlob[i].cbData);
1260 pbEncoded += setOf.rgBlob[i].cbData;
1264 for (i = 0; i < setOf.cBlob; i++)
1265 CryptMemFree(setOf.rgBlob[i].pbData);
1266 CryptMemFree(setOf.rgBlob);
1267 return ret;
1270 static BOOL CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, const CERT_RDN *rdn,
1271 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1272 DWORD *pcbEncoded)
1274 BOOL ret;
1275 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1277 __TRY
1279 DWORD i;
1281 ret = TRUE;
1282 if (rdn->cRDNAttr)
1284 setOf.cBlob = rdn->cRDNAttr;
1285 setOf.rgBlob = CryptMemAlloc(rdn->cRDNAttr *
1286 sizeof(CRYPT_DER_BLOB));
1287 if (!setOf.rgBlob)
1288 ret = FALSE;
1289 else
1290 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1292 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1294 setOf.rgBlob[i].cbData = 0;
1295 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1296 nameValueEncodeFunc, NULL, &setOf.rgBlob[i].cbData);
1297 if (ret)
1299 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1300 if (!setOf.rgBlob[i].pbData)
1301 ret = FALSE;
1302 else
1303 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1304 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1305 setOf.rgBlob[i].pbData, &setOf.rgBlob[i].cbData);
1307 if (!ret)
1309 /* Have to propagate index of failing character */
1310 *pcbEncoded = setOf.rgBlob[i].cbData;
1313 if (ret)
1314 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1315 pbEncoded, pcbEncoded);
1316 for (i = 0; i < setOf.cBlob; i++)
1317 CryptMemFree(setOf.rgBlob[i].pbData);
1319 __EXCEPT_PAGE_FAULT
1321 SetLastError(STATUS_ACCESS_VIOLATION);
1322 ret = FALSE;
1324 __ENDTRY
1325 CryptMemFree(setOf.rgBlob);
1326 return ret;
1329 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1330 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1331 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1333 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1334 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1335 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1336 DWORD *pcbEncoded)
1338 const CERT_NAME_VALUE *value = pvStructInfo;
1339 BOOL ret;
1341 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1342 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1343 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1344 else
1345 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1346 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1347 return ret;
1350 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1351 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1352 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1354 BOOL ret = TRUE;
1356 __TRY
1358 const CERT_NAME_INFO *info = pvStructInfo;
1359 DWORD bytesNeeded = 0, lenBytes, size, i;
1361 TRACE("encoding name with %d RDNs\n", info->cRDN);
1362 ret = TRUE;
1363 for (i = 0; ret && i < info->cRDN; i++)
1365 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1366 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1367 if (ret)
1368 bytesNeeded += size;
1369 else
1370 *pcbEncoded = size;
1372 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1373 bytesNeeded += 1 + lenBytes;
1374 if (ret)
1376 if (!pbEncoded)
1377 *pcbEncoded = bytesNeeded;
1378 else
1380 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1381 pbEncoded, pcbEncoded, bytesNeeded)))
1383 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1384 pbEncoded = *(BYTE **)pbEncoded;
1385 *pbEncoded++ = ASN_SEQUENCEOF;
1386 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1387 &lenBytes);
1388 pbEncoded += lenBytes;
1389 for (i = 0; ret && i < info->cRDN; i++)
1391 size = bytesNeeded;
1392 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1393 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1394 pbEncoded, &size);
1395 if (ret)
1397 pbEncoded += size;
1398 bytesNeeded -= size;
1400 else
1401 *pcbEncoded = size;
1407 __EXCEPT_PAGE_FAULT
1409 SetLastError(STATUS_ACCESS_VIOLATION);
1410 ret = FALSE;
1412 __ENDTRY
1413 return ret;
1416 static BOOL WINAPI CRYPT_AsnEncodeCTLVersion(DWORD dwCertEncodingType,
1417 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1418 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1420 const DWORD *ver = pvStructInfo;
1421 BOOL ret;
1423 /* CTL_V1 is not encoded */
1424 if (*ver == CTL_V1)
1426 *pcbEncoded = 0;
1427 ret = TRUE;
1429 else
1430 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
1431 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1432 return ret;
1435 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
1436 * if they are empty and the OID is not empty (otherwise omits them.)
1438 static BOOL WINAPI CRYPT_AsnEncodeCTLSubjectAlgorithm(
1439 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1440 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1441 DWORD *pcbEncoded)
1443 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
1444 BOOL ret;
1445 struct AsnEncodeSequenceItem items[2] = {
1446 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
1448 DWORD cItem = 1;
1450 if (algo->pszObjId)
1452 static const BYTE asn1Null[] = { ASN_NULL, 0 };
1453 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
1454 (LPBYTE)asn1Null };
1456 if (algo->Parameters.cbData)
1457 items[cItem].pvStructInfo = &algo->Parameters;
1458 else
1459 items[cItem].pvStructInfo = &nullBlob;
1460 items[cItem].encodeFunc = CRYPT_CopyEncodedBlob;
1461 cItem++;
1463 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1464 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1465 return ret;
1468 static BOOL CRYPT_AsnEncodeCTLEntry(const CTL_ENTRY *entry,
1469 BYTE *pbEncoded, DWORD *pcbEncoded)
1471 struct AsnEncodeSequenceItem items[2] = {
1472 { &entry->SubjectIdentifier, CRYPT_AsnEncodeOctets, 0 },
1473 { &entry->cAttribute, CRYPT_AsnEncodePKCSAttributes, 0 },
1475 BOOL ret;
1477 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1478 sizeof(items) / sizeof(items[0]), 0, NULL, pbEncoded, pcbEncoded);
1479 return ret;
1482 struct CTLEntries
1484 DWORD cEntry;
1485 CTL_ENTRY *rgEntry;
1488 static BOOL WINAPI CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType,
1489 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1490 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1492 BOOL ret;
1493 DWORD bytesNeeded, dataLen, lenBytes, i;
1494 const struct CTLEntries *entries = pvStructInfo;
1496 ret = TRUE;
1497 for (i = 0, dataLen = 0; ret && i < entries->cEntry; i++)
1499 DWORD size;
1501 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i], NULL, &size);
1502 if (ret)
1503 dataLen += size;
1505 if (ret)
1507 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1508 bytesNeeded = 1 + lenBytes + dataLen;
1509 if (!pbEncoded)
1510 *pcbEncoded = bytesNeeded;
1511 else
1513 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1514 pbEncoded, pcbEncoded, bytesNeeded)))
1516 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1517 pbEncoded = *(BYTE **)pbEncoded;
1518 *pbEncoded++ = ASN_SEQUENCEOF;
1519 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1520 pbEncoded += lenBytes;
1521 for (i = 0; ret && i < entries->cEntry; i++)
1523 DWORD size = dataLen;
1525 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i],
1526 pbEncoded, &size);
1527 pbEncoded += size;
1528 dataLen -= size;
1533 return ret;
1536 static BOOL WINAPI CRYPT_AsnEncodeCTL(DWORD dwCertEncodingType,
1537 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1538 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1540 BOOL ret = FALSE;
1542 __TRY
1544 const CTL_INFO *info = pvStructInfo;
1545 struct AsnEncodeSequenceItem items[9] = {
1546 { &info->dwVersion, CRYPT_AsnEncodeCTLVersion, 0 },
1547 { &info->SubjectUsage, CRYPT_AsnEncodeEnhancedKeyUsage, 0 },
1549 struct AsnConstructedItem constructed = { 0 };
1550 DWORD cItem = 2;
1552 if (info->ListIdentifier.cbData)
1554 items[cItem].pvStructInfo = &info->ListIdentifier;
1555 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
1556 cItem++;
1558 if (info->SequenceNumber.cbData)
1560 items[cItem].pvStructInfo = &info->SequenceNumber;
1561 items[cItem].encodeFunc = CRYPT_AsnEncodeInteger;
1562 cItem++;
1564 items[cItem].pvStructInfo = &info->ThisUpdate;
1565 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1566 cItem++;
1567 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
1569 items[cItem].pvStructInfo = &info->NextUpdate;
1570 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1571 cItem++;
1573 items[cItem].pvStructInfo = &info->SubjectAlgorithm;
1574 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLSubjectAlgorithm;
1575 cItem++;
1576 if (info->cCTLEntry)
1578 items[cItem].pvStructInfo = &info->cCTLEntry;
1579 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLEntries;
1580 cItem++;
1582 if (info->cExtension)
1584 constructed.tag = 0;
1585 constructed.pvStructInfo = &info->cExtension;
1586 constructed.encodeFunc = CRYPT_AsnEncodeExtensions;
1587 items[cItem].pvStructInfo = &constructed;
1588 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1589 cItem++;
1591 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1592 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1594 __EXCEPT_PAGE_FAULT
1596 SetLastError(STATUS_ACCESS_VIOLATION);
1598 __ENDTRY
1599 return ret;
1602 static BOOL CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType,
1603 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1604 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1606 BOOL ret = FALSE;
1608 __TRY
1610 const CRYPT_SMIME_CAPABILITY *capability = pvStructInfo;
1612 if (!capability->pszObjId)
1613 SetLastError(E_INVALIDARG);
1614 else
1616 struct AsnEncodeSequenceItem items[] = {
1617 { capability->pszObjId, CRYPT_AsnEncodeOid, 0 },
1618 { &capability->Parameters, CRYPT_CopyEncodedBlob, 0 },
1621 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1622 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1623 pcbEncoded);
1626 __EXCEPT_PAGE_FAULT
1628 SetLastError(STATUS_ACCESS_VIOLATION);
1630 __ENDTRY
1631 return ret;
1634 static BOOL WINAPI CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType,
1635 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1636 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1638 BOOL ret = FALSE;
1640 __TRY
1642 DWORD bytesNeeded, dataLen, lenBytes, i;
1643 const CRYPT_SMIME_CAPABILITIES *capabilities = pvStructInfo;
1645 ret = TRUE;
1646 for (i = 0, dataLen = 0; ret && i < capabilities->cCapability; i++)
1648 DWORD size;
1650 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType, NULL,
1651 &capabilities->rgCapability[i], 0, NULL, NULL, &size);
1652 if (ret)
1653 dataLen += size;
1655 if (ret)
1657 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1658 bytesNeeded = 1 + lenBytes + dataLen;
1659 if (!pbEncoded)
1660 *pcbEncoded = bytesNeeded;
1661 else
1663 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1664 pbEncoded, pcbEncoded, bytesNeeded)))
1666 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1667 pbEncoded = *(BYTE **)pbEncoded;
1668 *pbEncoded++ = ASN_SEQUENCEOF;
1669 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1670 pbEncoded += lenBytes;
1671 for (i = 0; i < capabilities->cCapability; i++)
1673 DWORD size = dataLen;
1675 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType,
1676 NULL, &capabilities->rgCapability[i], 0, NULL,
1677 pbEncoded, &size);
1678 pbEncoded += size;
1679 dataLen -= size;
1685 __EXCEPT_PAGE_FAULT
1687 SetLastError(STATUS_ACCESS_VIOLATION);
1689 __ENDTRY
1690 return ret;
1693 static BOOL WINAPI CRYPT_AsnEncodeNoticeNumbers(DWORD dwCertEncodingType,
1694 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1695 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1697 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
1698 DWORD bytesNeeded, dataLen, lenBytes, i;
1699 BOOL ret = TRUE;
1701 for (i = 0, dataLen = 0; ret && i < noticeRef->cNoticeNumbers; i++)
1703 DWORD size;
1705 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
1706 &noticeRef->rgNoticeNumbers[i], 0, NULL, NULL, &size);
1707 if (ret)
1708 dataLen += size;
1710 if (ret)
1712 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1713 bytesNeeded = 1 + lenBytes + dataLen;
1714 if (!pbEncoded)
1715 *pcbEncoded = bytesNeeded;
1716 else
1718 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1719 pcbEncoded, bytesNeeded)))
1721 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1722 pbEncoded = *(BYTE **)pbEncoded;
1723 *pbEncoded++ = ASN_SEQUENCE;
1724 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1725 pbEncoded += lenBytes;
1726 for (i = 0; i < noticeRef->cNoticeNumbers; i++)
1728 DWORD size = dataLen;
1730 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
1731 &noticeRef->rgNoticeNumbers[i], 0, NULL, pbEncoded, &size);
1732 pbEncoded += size;
1733 dataLen -= size;
1738 return ret;
1741 static BOOL WINAPI CRYPT_AsnEncodeNoticeReference(DWORD dwCertEncodingType,
1742 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1743 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1745 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
1746 BOOL ret;
1747 CERT_NAME_VALUE orgValue = { CERT_RDN_IA5_STRING,
1748 { 0, (LPBYTE)noticeRef->pszOrganization } };
1749 struct AsnEncodeSequenceItem items[] = {
1750 { &orgValue, CRYPT_AsnEncodeNameValue, 0 },
1751 { noticeRef, CRYPT_AsnEncodeNoticeNumbers, 0 },
1754 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1755 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1756 pcbEncoded);
1757 return ret;
1760 static BOOL WINAPI CRYPT_AsnEncodePolicyQualifierUserNotice(
1761 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1762 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1763 DWORD *pcbEncoded)
1765 BOOL ret = FALSE;
1767 __TRY
1769 const CERT_POLICY_QUALIFIER_USER_NOTICE *notice = pvStructInfo;
1770 struct AsnEncodeSequenceItem items[2];
1771 CERT_NAME_VALUE displayTextValue;
1772 DWORD cItem = 0;
1774 ret = TRUE;
1775 if (notice->pNoticeReference)
1777 items[cItem].encodeFunc = CRYPT_AsnEncodeNoticeReference;
1778 items[cItem].pvStructInfo = notice->pNoticeReference;
1779 cItem++;
1781 if (notice->pszDisplayText)
1783 displayTextValue.dwValueType = CERT_RDN_BMP_STRING;
1784 displayTextValue.Value.cbData = 0;
1785 displayTextValue.Value.pbData = (LPBYTE)notice->pszDisplayText;
1786 items[cItem].encodeFunc = CRYPT_AsnEncodeNameValue;
1787 items[cItem].pvStructInfo = &displayTextValue;
1788 cItem++;
1790 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1791 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1793 __EXCEPT_PAGE_FAULT
1795 SetLastError(STATUS_ACCESS_VIOLATION);
1797 __ENDTRY
1798 return ret;
1801 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1802 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1803 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1805 BOOL ret = FALSE;
1807 __TRY
1809 const CRYPT_ATTRIBUTE *attr = pvStructInfo;
1811 if (!attr->pszObjId)
1812 SetLastError(E_INVALIDARG);
1813 else
1815 struct AsnEncodeSequenceItem items[2] = {
1816 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1817 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1820 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1821 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1822 pcbEncoded);
1825 __EXCEPT_PAGE_FAULT
1827 SetLastError(STATUS_ACCESS_VIOLATION);
1829 __ENDTRY
1830 return ret;
1833 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1834 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1835 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1837 BOOL ret = FALSE;
1839 __TRY
1841 const CRYPT_ATTRIBUTES *attributes = pvStructInfo;
1842 struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
1843 sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
1845 ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
1846 &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1848 __EXCEPT_PAGE_FAULT
1850 SetLastError(STATUS_ACCESS_VIOLATION);
1852 __ENDTRY
1853 return ret;
1856 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1857 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
1858 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1859 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1860 DWORD *pcbEncoded)
1862 const CRYPT_CONTENT_INFO *info = pvStructInfo;
1863 struct AsnEncodeSequenceItem items[2] = {
1864 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1865 { NULL, NULL, 0 },
1867 struct AsnConstructedItem constructed = { 0 };
1868 DWORD cItem = 1;
1870 if (info->Content.cbData)
1872 constructed.tag = 0;
1873 constructed.pvStructInfo = &info->Content;
1874 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1875 items[cItem].pvStructInfo = &constructed;
1876 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1877 cItem++;
1879 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1880 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1883 BOOL CRYPT_AsnEncodePKCSDigestedData(const CRYPT_DIGESTED_DATA *digestedData,
1884 void *pvData, DWORD *pcbData)
1886 struct AsnEncodeSequenceItem items[] = {
1887 { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1888 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
1889 0 },
1890 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1891 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1894 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1895 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
1898 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1899 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1900 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1902 BOOL ret = FALSE;
1904 __TRY
1906 const CRYPT_CONTENT_INFO *info = pvStructInfo;
1908 if (!info->pszObjId)
1909 SetLastError(E_INVALIDARG);
1910 else
1911 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
1912 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1913 pcbEncoded);
1915 __EXCEPT_PAGE_FAULT
1917 SetLastError(STATUS_ACCESS_VIOLATION);
1919 __ENDTRY
1920 return ret;
1923 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1924 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1925 DWORD *pcbEncoded)
1927 BOOL ret = TRUE;
1928 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1929 DWORD bytesNeeded, lenBytes, encodedLen;
1931 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1932 strlenW(str);
1933 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1934 bytesNeeded = 1 + lenBytes + encodedLen;
1935 if (!pbEncoded)
1936 *pcbEncoded = bytesNeeded;
1937 else
1939 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1940 pbEncoded, pcbEncoded, bytesNeeded)))
1942 DWORD i;
1944 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1945 pbEncoded = *(BYTE **)pbEncoded;
1946 *pbEncoded++ = tag;
1947 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1948 pbEncoded += lenBytes;
1949 for (i = 0; i < encodedLen; i++)
1950 *pbEncoded++ = (BYTE)str[i];
1953 return ret;
1956 static void CRYPT_FreeSpace(PCRYPT_ENCODE_PARA pEncodePara, LPVOID pv)
1958 if (pEncodePara && pEncodePara->pfnFree)
1959 pEncodePara->pfnFree(pv);
1960 else
1961 LocalFree(pv);
1964 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
1965 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1966 DWORD *pcbEncoded)
1968 BOOL ret = TRUE;
1969 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1970 DWORD bytesNeeded, lenBytes, encodedLen;
1972 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1973 strlenW(str);
1974 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1975 bytesNeeded = 1 + lenBytes + encodedLen;
1976 if (!pbEncoded)
1977 *pcbEncoded = bytesNeeded;
1978 else
1980 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1981 pbEncoded, pcbEncoded, bytesNeeded)))
1983 DWORD i;
1984 BYTE *ptr;
1986 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1987 ptr = *(BYTE **)pbEncoded;
1988 else
1989 ptr = pbEncoded;
1990 *ptr++ = ASN_NUMERICSTRING;
1991 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
1992 ptr += lenBytes;
1993 for (i = 0; ret && i < encodedLen; i++)
1995 if (isdigitW(str[i]))
1996 *ptr++ = (BYTE)str[i];
1997 else
1999 *pcbEncoded = i;
2000 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
2001 ret = FALSE;
2004 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2005 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2008 return ret;
2011 static inline int isprintableW(WCHAR wc)
2013 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
2014 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
2015 wc == '/' || wc == ':' || wc == '=' || wc == '?';
2018 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
2019 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
2020 DWORD *pcbEncoded)
2022 BOOL ret = TRUE;
2023 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2024 DWORD bytesNeeded, lenBytes, encodedLen;
2026 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
2027 strlenW(str);
2028 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2029 bytesNeeded = 1 + lenBytes + encodedLen;
2030 if (!pbEncoded)
2031 *pcbEncoded = bytesNeeded;
2032 else
2034 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2035 pbEncoded, pcbEncoded, bytesNeeded)))
2037 DWORD i;
2038 BYTE *ptr;
2040 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2041 ptr = *(BYTE **)pbEncoded;
2042 else
2043 ptr = pbEncoded;
2044 *ptr++ = ASN_PRINTABLESTRING;
2045 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2046 ptr += lenBytes;
2047 for (i = 0; ret && i < encodedLen; i++)
2049 if (isprintableW(str[i]))
2050 *ptr++ = (BYTE)str[i];
2051 else
2053 *pcbEncoded = i;
2054 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
2055 ret = FALSE;
2058 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2059 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2062 return ret;
2065 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
2066 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
2067 DWORD *pcbEncoded)
2069 BOOL ret = TRUE;
2070 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2071 DWORD bytesNeeded, lenBytes, encodedLen;
2073 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
2074 strlenW(str);
2075 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2076 bytesNeeded = 1 + lenBytes + encodedLen;
2077 if (!pbEncoded)
2078 *pcbEncoded = bytesNeeded;
2079 else
2081 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2082 pbEncoded, pcbEncoded, bytesNeeded)))
2084 DWORD i;
2085 BYTE *ptr;
2087 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2088 ptr = *(BYTE **)pbEncoded;
2089 else
2090 ptr = pbEncoded;
2091 *ptr++ = ASN_IA5STRING;
2092 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2093 ptr += lenBytes;
2094 for (i = 0; ret && i < encodedLen; i++)
2096 if (str[i] <= 0x7f)
2097 *ptr++ = (BYTE)str[i];
2098 else
2100 *pcbEncoded = i;
2101 SetLastError(CRYPT_E_INVALID_IA5_STRING);
2102 ret = FALSE;
2105 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2106 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2109 return ret;
2112 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
2113 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
2114 DWORD *pcbEncoded)
2116 BOOL ret = TRUE;
2117 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2118 DWORD bytesNeeded, lenBytes, strLen;
2120 /* FIXME: doesn't handle composite characters */
2121 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
2122 strlenW(str);
2123 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
2124 bytesNeeded = 1 + lenBytes + strLen * 4;
2125 if (!pbEncoded)
2126 *pcbEncoded = bytesNeeded;
2127 else
2129 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2130 pbEncoded, pcbEncoded, bytesNeeded)))
2132 DWORD i;
2134 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2135 pbEncoded = *(BYTE **)pbEncoded;
2136 *pbEncoded++ = ASN_UNIVERSALSTRING;
2137 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
2138 pbEncoded += lenBytes;
2139 for (i = 0; i < strLen; i++)
2141 *pbEncoded++ = 0;
2142 *pbEncoded++ = 0;
2143 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
2144 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
2148 return ret;
2151 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
2152 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2153 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2155 BOOL ret = FALSE;
2157 __TRY
2159 const CERT_NAME_VALUE *value = pvStructInfo;
2161 switch (value->dwValueType)
2163 case CERT_RDN_ANY_TYPE:
2164 case CERT_RDN_ENCODED_BLOB:
2165 case CERT_RDN_OCTET_STRING:
2166 SetLastError(CRYPT_E_NOT_CHAR_STRING);
2167 break;
2168 case CERT_RDN_NUMERIC_STRING:
2169 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
2170 pbEncoded, pcbEncoded);
2171 break;
2172 case CERT_RDN_PRINTABLE_STRING:
2173 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
2174 pbEncoded, pcbEncoded);
2175 break;
2176 case CERT_RDN_TELETEX_STRING:
2177 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
2178 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2179 break;
2180 case CERT_RDN_VIDEOTEX_STRING:
2181 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
2182 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2183 break;
2184 case CERT_RDN_IA5_STRING:
2185 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
2186 pbEncoded, pcbEncoded);
2187 break;
2188 case CERT_RDN_GRAPHIC_STRING:
2189 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
2190 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2191 break;
2192 case CERT_RDN_VISIBLE_STRING:
2193 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
2194 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2195 break;
2196 case CERT_RDN_GENERAL_STRING:
2197 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
2198 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2199 break;
2200 case CERT_RDN_UNIVERSAL_STRING:
2201 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
2202 pbEncoded, pcbEncoded);
2203 break;
2204 case CERT_RDN_BMP_STRING:
2205 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
2206 pbEncoded, pcbEncoded);
2207 break;
2208 case CERT_RDN_UTF8_STRING:
2209 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
2210 pbEncoded, pcbEncoded);
2211 break;
2212 default:
2213 SetLastError(CRYPT_E_ASN1_CHOICE);
2216 __EXCEPT_PAGE_FAULT
2218 SetLastError(STATUS_ACCESS_VIOLATION);
2220 __ENDTRY
2221 return ret;
2224 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
2225 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2226 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2228 BOOL ret;
2230 __TRY
2232 const CERT_NAME_INFO *info = pvStructInfo;
2233 DWORD bytesNeeded = 0, lenBytes, size, i;
2235 TRACE("encoding name with %d RDNs\n", info->cRDN);
2236 ret = TRUE;
2237 for (i = 0; ret && i < info->cRDN; i++)
2239 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
2240 CRYPT_AsnEncodeNameValue, NULL, &size);
2241 if (ret)
2242 bytesNeeded += size;
2244 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2245 bytesNeeded += 1 + lenBytes;
2246 if (ret)
2248 if (!pbEncoded)
2249 *pcbEncoded = bytesNeeded;
2250 else
2252 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2253 pbEncoded, pcbEncoded, bytesNeeded)))
2255 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2256 pbEncoded = *(BYTE **)pbEncoded;
2257 *pbEncoded++ = ASN_SEQUENCEOF;
2258 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
2259 &lenBytes);
2260 pbEncoded += lenBytes;
2261 for (i = 0; ret && i < info->cRDN; i++)
2263 size = bytesNeeded;
2264 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
2265 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, pbEncoded,
2266 &size);
2267 if (ret)
2269 pbEncoded += size;
2270 bytesNeeded -= size;
2277 __EXCEPT_PAGE_FAULT
2279 SetLastError(STATUS_ACCESS_VIOLATION);
2280 ret = FALSE;
2282 __ENDTRY
2283 return ret;
2286 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
2287 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2288 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2290 BOOL val = *(const BOOL *)pvStructInfo, ret;
2292 TRACE("%d\n", val);
2294 if (!pbEncoded)
2296 *pcbEncoded = 3;
2297 ret = TRUE;
2299 else if (*pcbEncoded < 3)
2301 *pcbEncoded = 3;
2302 SetLastError(ERROR_MORE_DATA);
2303 ret = FALSE;
2305 else
2307 *pcbEncoded = 3;
2308 *pbEncoded++ = ASN_BOOL;
2309 *pbEncoded++ = 1;
2310 *pbEncoded++ = val ? 0xff : 0;
2311 ret = TRUE;
2313 TRACE("returning %d (%08x)\n", ret, GetLastError());
2314 return ret;
2317 static BOOL WINAPI CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType,
2318 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2319 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2321 const CERT_ALT_NAME_ENTRY *entry = pvStructInfo;
2322 BOOL ret;
2323 DWORD dataLen;
2324 BYTE tag;
2326 ret = TRUE;
2327 switch (entry->dwAltNameChoice)
2329 case CERT_ALT_NAME_RFC822_NAME:
2330 case CERT_ALT_NAME_DNS_NAME:
2331 case CERT_ALT_NAME_URL:
2332 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2333 if (entry->u.pwszURL)
2335 DWORD i;
2337 /* Not + 1: don't encode the NULL-terminator */
2338 dataLen = lstrlenW(entry->u.pwszURL);
2339 for (i = 0; ret && i < dataLen; i++)
2341 if (entry->u.pwszURL[i] > 0x7f)
2343 SetLastError(CRYPT_E_INVALID_IA5_STRING);
2344 ret = FALSE;
2345 *pcbEncoded = i;
2349 else
2350 dataLen = 0;
2351 break;
2352 case CERT_ALT_NAME_DIRECTORY_NAME:
2353 tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1);
2354 dataLen = entry->u.DirectoryName.cbData;
2355 break;
2356 case CERT_ALT_NAME_IP_ADDRESS:
2357 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2358 dataLen = entry->u.IPAddress.cbData;
2359 break;
2360 case CERT_ALT_NAME_REGISTERED_ID:
2362 struct AsnEncodeTagSwappedItem swapped =
2363 { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID,
2364 CRYPT_AsnEncodeOid };
2366 return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded,
2367 pcbEncoded);
2369 case CERT_ALT_NAME_OTHER_NAME:
2370 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
2371 return FALSE;
2372 default:
2373 SetLastError(E_INVALIDARG);
2374 return FALSE;
2376 if (ret)
2378 DWORD bytesNeeded, lenBytes;
2380 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2381 bytesNeeded = 1 + dataLen + lenBytes;
2382 if (!pbEncoded)
2383 *pcbEncoded = bytesNeeded;
2384 else if (*pcbEncoded < bytesNeeded)
2386 SetLastError(ERROR_MORE_DATA);
2387 *pcbEncoded = bytesNeeded;
2388 ret = FALSE;
2390 else
2392 *pbEncoded++ = tag;
2393 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2394 pbEncoded += lenBytes;
2395 switch (entry->dwAltNameChoice)
2397 case CERT_ALT_NAME_RFC822_NAME:
2398 case CERT_ALT_NAME_DNS_NAME:
2399 case CERT_ALT_NAME_URL:
2401 DWORD i;
2403 for (i = 0; i < dataLen; i++)
2404 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
2405 break;
2407 case CERT_ALT_NAME_DIRECTORY_NAME:
2408 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen);
2409 break;
2410 case CERT_ALT_NAME_IP_ADDRESS:
2411 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
2412 break;
2414 if (ret)
2415 *pcbEncoded = bytesNeeded;
2418 TRACE("returning %d (%08x)\n", ret, GetLastError());
2419 return ret;
2422 static BOOL WINAPI CRYPT_AsnEncodeIntegerSwapBytes(DWORD dwCertEncodingType,
2423 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2424 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2426 BOOL ret;
2428 __TRY
2430 const CRYPT_DATA_BLOB *blob = pvStructInfo;
2431 CRYPT_DATA_BLOB newBlob = { blob->cbData, NULL };
2433 ret = TRUE;
2434 if (newBlob.cbData)
2436 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2437 if (newBlob.pbData)
2439 DWORD i;
2441 for (i = 0; i < newBlob.cbData; i++)
2442 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2444 else
2445 ret = FALSE;
2447 if (ret)
2448 ret = CRYPT_AsnEncodeInteger(dwCertEncodingType, lpszStructType,
2449 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2450 CryptMemFree(newBlob.pbData);
2452 __EXCEPT_PAGE_FAULT
2454 SetLastError(STATUS_ACCESS_VIOLATION);
2455 ret = FALSE;
2457 __ENDTRY
2458 return ret;
2461 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
2462 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2463 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2465 BOOL ret;
2467 __TRY
2469 const CERT_AUTHORITY_KEY_ID_INFO *info = pvStructInfo;
2470 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2471 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2472 struct AsnConstructedItem constructed = { 0 };
2473 DWORD cItem = 0, cSwapped = 0;
2475 if (info->KeyId.cbData)
2477 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2478 swapped[cSwapped].pvStructInfo = &info->KeyId;
2479 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2480 items[cItem].pvStructInfo = &swapped[cSwapped];
2481 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2482 cSwapped++;
2483 cItem++;
2485 if (info->CertIssuer.cbData)
2487 constructed.tag = 1;
2488 constructed.pvStructInfo = &info->CertIssuer;
2489 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2490 items[cItem].pvStructInfo = &constructed;
2491 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2492 cItem++;
2494 if (info->CertSerialNumber.cbData)
2496 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2497 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2498 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2499 items[cItem].pvStructInfo = &swapped[cSwapped];
2500 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2501 cSwapped++;
2502 cItem++;
2504 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2505 pEncodePara, pbEncoded, pcbEncoded);
2507 __EXCEPT_PAGE_FAULT
2509 SetLastError(STATUS_ACCESS_VIOLATION);
2510 ret = FALSE;
2512 __ENDTRY
2513 return ret;
2516 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2517 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2518 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2520 BOOL ret;
2522 __TRY
2524 const CERT_ALT_NAME_INFO *info = pvStructInfo;
2525 DWORD bytesNeeded, dataLen, lenBytes, i;
2527 ret = TRUE;
2528 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2529 * can't encode an erroneous entry index if it's bigger than this.
2531 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2533 DWORD len;
2535 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, NULL,
2536 &info->rgAltEntry[i], 0, NULL, NULL, &len);
2537 if (ret)
2538 dataLen += len;
2539 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2541 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2542 * the bad character, now set the index of the bad
2543 * entry
2545 *pcbEncoded = (BYTE)i <<
2546 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2549 if (ret)
2551 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2552 bytesNeeded = 1 + lenBytes + dataLen;
2553 if (!pbEncoded)
2555 *pcbEncoded = bytesNeeded;
2556 ret = TRUE;
2558 else
2560 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2561 pbEncoded, pcbEncoded, bytesNeeded)))
2563 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2564 pbEncoded = *(BYTE **)pbEncoded;
2565 *pbEncoded++ = ASN_SEQUENCEOF;
2566 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2567 pbEncoded += lenBytes;
2568 for (i = 0; ret && i < info->cAltEntry; i++)
2570 DWORD len = dataLen;
2572 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType,
2573 NULL, &info->rgAltEntry[i], 0, NULL, pbEncoded, &len);
2574 if (ret)
2576 pbEncoded += len;
2577 dataLen -= len;
2584 __EXCEPT_PAGE_FAULT
2586 SetLastError(STATUS_ACCESS_VIOLATION);
2587 ret = FALSE;
2589 __ENDTRY
2590 return ret;
2593 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2594 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2595 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2597 BOOL ret;
2599 __TRY
2601 const CERT_AUTHORITY_KEY_ID2_INFO *info = pvStructInfo;
2602 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2603 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2604 DWORD cItem = 0, cSwapped = 0;
2606 if (info->KeyId.cbData)
2608 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2609 swapped[cSwapped].pvStructInfo = &info->KeyId;
2610 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2611 items[cItem].pvStructInfo = &swapped[cSwapped];
2612 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2613 cSwapped++;
2614 cItem++;
2616 if (info->AuthorityCertIssuer.cAltEntry)
2618 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2619 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2620 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2621 items[cItem].pvStructInfo = &swapped[cSwapped];
2622 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2623 cSwapped++;
2624 cItem++;
2626 if (info->AuthorityCertSerialNumber.cbData)
2628 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2629 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2630 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2631 items[cItem].pvStructInfo = &swapped[cSwapped];
2632 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2633 cSwapped++;
2634 cItem++;
2636 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2637 pEncodePara, pbEncoded, pcbEncoded);
2639 __EXCEPT_PAGE_FAULT
2641 SetLastError(STATUS_ACCESS_VIOLATION);
2642 ret = FALSE;
2644 __ENDTRY
2645 return ret;
2648 static BOOL CRYPT_AsnEncodeAccessDescription(
2649 const CERT_ACCESS_DESCRIPTION *descr, BYTE *pbEncoded, DWORD *pcbEncoded)
2651 struct AsnEncodeSequenceItem items[] = {
2652 { descr->pszAccessMethod, CRYPT_AsnEncodeOid, 0 },
2653 { &descr->AccessLocation, CRYPT_AsnEncodeAltNameEntry, 0 },
2656 if (!descr->pszAccessMethod)
2658 SetLastError(E_INVALIDARG);
2659 return FALSE;
2661 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
2662 sizeof(items) / sizeof(items[0]), 0, NULL, pbEncoded, pcbEncoded);
2665 static BOOL WINAPI CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType,
2666 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2667 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2669 BOOL ret;
2671 __TRY
2673 DWORD bytesNeeded, dataLen, lenBytes, i;
2674 const CERT_AUTHORITY_INFO_ACCESS *info = pvStructInfo;
2676 ret = TRUE;
2677 for (i = 0, dataLen = 0; ret && i < info->cAccDescr; i++)
2679 DWORD size;
2681 ret = CRYPT_AsnEncodeAccessDescription(&info->rgAccDescr[i], NULL,
2682 &size);
2683 if (ret)
2684 dataLen += size;
2686 if (ret)
2688 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2689 bytesNeeded = 1 + lenBytes + dataLen;
2690 if (!pbEncoded)
2691 *pcbEncoded = bytesNeeded;
2692 else
2694 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2695 pbEncoded, pcbEncoded, bytesNeeded)))
2697 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2698 pbEncoded = *(BYTE **)pbEncoded;
2699 *pbEncoded++ = ASN_SEQUENCEOF;
2700 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2701 pbEncoded += lenBytes;
2702 for (i = 0; i < info->cAccDescr; i++)
2704 DWORD size = dataLen;
2706 ret = CRYPT_AsnEncodeAccessDescription(
2707 &info->rgAccDescr[i], pbEncoded, &size);
2708 pbEncoded += size;
2709 dataLen -= size;
2715 __EXCEPT_PAGE_FAULT
2717 SetLastError(STATUS_ACCESS_VIOLATION);
2718 ret = FALSE;
2720 __ENDTRY
2721 return ret;
2724 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2725 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2726 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2728 BOOL ret;
2730 __TRY
2732 const CERT_BASIC_CONSTRAINTS_INFO *info = pvStructInfo;
2733 struct AsnEncodeSequenceItem items[3] = {
2734 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2735 { 0 }
2737 DWORD cItem = 1;
2739 if (info->fPathLenConstraint)
2741 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2742 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2743 cItem++;
2745 if (info->cSubtreesConstraint)
2747 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2748 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2749 cItem++;
2751 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2752 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2754 __EXCEPT_PAGE_FAULT
2756 SetLastError(STATUS_ACCESS_VIOLATION);
2757 ret = FALSE;
2759 __ENDTRY
2760 return ret;
2763 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2764 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2765 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2767 BOOL ret;
2769 __TRY
2771 const CERT_BASIC_CONSTRAINTS2_INFO *info = pvStructInfo;
2772 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2773 DWORD cItem = 0;
2775 if (info->fCA)
2777 items[cItem].pvStructInfo = &info->fCA;
2778 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2779 cItem++;
2781 if (info->fPathLenConstraint)
2783 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2784 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2785 cItem++;
2787 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2788 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2790 __EXCEPT_PAGE_FAULT
2792 SetLastError(STATUS_ACCESS_VIOLATION);
2793 ret = FALSE;
2795 __ENDTRY
2796 return ret;
2799 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType,
2800 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2801 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2803 DWORD cPolicyQualifier = *(DWORD *)pvStructInfo;
2804 const CERT_POLICY_QUALIFIER_INFO *rgPolicyQualifier =
2805 *(const CERT_POLICY_QUALIFIER_INFO **)
2806 ((LPBYTE)pvStructInfo + sizeof(DWORD));
2807 BOOL ret;
2809 if (!cPolicyQualifier)
2811 *pcbEncoded = 0;
2812 ret = TRUE;
2814 else
2816 struct AsnEncodeSequenceItem items[2] = {
2817 { NULL, CRYPT_AsnEncodeOid, 0 },
2818 { NULL, CRYPT_CopyEncodedBlob, 0 },
2820 DWORD bytesNeeded = 0, lenBytes, size, i;
2822 ret = TRUE;
2823 for (i = 0; ret && i < cPolicyQualifier; i++)
2825 items[0].pvStructInfo = rgPolicyQualifier[i].pszPolicyQualifierId;
2826 items[1].pvStructInfo = &rgPolicyQualifier[i].Qualifier;
2827 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2828 sizeof(items) / sizeof(items[0]),
2829 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
2830 if (ret)
2831 bytesNeeded += size;
2833 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2834 bytesNeeded += 1 + lenBytes;
2835 if (ret)
2837 if (!pbEncoded)
2838 *pcbEncoded = bytesNeeded;
2839 else
2841 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2842 pbEncoded, pcbEncoded, bytesNeeded)))
2844 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2845 pbEncoded = *(BYTE **)pbEncoded;
2846 *pbEncoded++ = ASN_SEQUENCEOF;
2847 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
2848 &lenBytes);
2849 pbEncoded += lenBytes;
2850 for (i = 0; ret && i < cPolicyQualifier; i++)
2852 items[0].pvStructInfo =
2853 rgPolicyQualifier[i].pszPolicyQualifierId;
2854 items[1].pvStructInfo =
2855 &rgPolicyQualifier[i].Qualifier;
2856 size = bytesNeeded;
2857 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2858 sizeof(items) / sizeof(items[0]),
2859 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
2860 &size);
2861 if (ret)
2863 pbEncoded += size;
2864 bytesNeeded -= size;
2871 return ret;
2874 static BOOL CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType,
2875 const CERT_POLICY_INFO *info, DWORD dwFlags, BYTE *pbEncoded,
2876 DWORD *pcbEncoded)
2878 struct AsnEncodeSequenceItem items[2] = {
2879 { info->pszPolicyIdentifier, CRYPT_AsnEncodeOid, 0 },
2880 { &info->cPolicyQualifier, CRYPT_AsnEncodeCertPolicyQualifiers, 0 },
2882 BOOL ret;
2884 if (!info->pszPolicyIdentifier)
2886 SetLastError(E_INVALIDARG);
2887 return FALSE;
2889 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2890 sizeof(items) / sizeof(items[0]), dwFlags, NULL, pbEncoded, pcbEncoded);
2891 return ret;
2894 static BOOL WINAPI CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType,
2895 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2896 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2898 BOOL ret = FALSE;
2900 __TRY
2902 const CERT_POLICIES_INFO *info = pvStructInfo;
2903 DWORD bytesNeeded = 0, lenBytes, size, i;
2905 ret = TRUE;
2906 for (i = 0; ret && i < info->cPolicyInfo; i++)
2908 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
2909 &info->rgPolicyInfo[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
2910 &size);
2911 if (ret)
2912 bytesNeeded += size;
2914 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2915 bytesNeeded += 1 + lenBytes;
2916 if (ret)
2918 if (!pbEncoded)
2919 *pcbEncoded = bytesNeeded;
2920 else
2922 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2923 pbEncoded, pcbEncoded, bytesNeeded)))
2925 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2926 pbEncoded = *(BYTE **)pbEncoded;
2927 *pbEncoded++ = ASN_SEQUENCEOF;
2928 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
2929 &lenBytes);
2930 pbEncoded += lenBytes;
2931 for (i = 0; ret && i < info->cPolicyInfo; i++)
2933 size = bytesNeeded;
2934 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
2935 &info->rgPolicyInfo[i],
2936 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pbEncoded, &size);
2937 if (ret)
2939 pbEncoded += size;
2940 bytesNeeded -= size;
2947 __EXCEPT_PAGE_FAULT
2949 SetLastError(STATUS_ACCESS_VIOLATION);
2951 __ENDTRY
2952 return ret;
2955 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
2956 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2957 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2959 BOOL ret;
2961 __TRY
2963 const BLOBHEADER *hdr = pvStructInfo;
2965 if (hdr->bType != PUBLICKEYBLOB)
2967 SetLastError(E_INVALIDARG);
2968 ret = FALSE;
2970 else
2972 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
2973 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
2974 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
2975 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
2976 struct AsnEncodeSequenceItem items[] = {
2977 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
2978 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
2981 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2982 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
2983 pcbEncoded);
2986 __EXCEPT_PAGE_FAULT
2988 SetLastError(STATUS_ACCESS_VIOLATION);
2989 ret = FALSE;
2991 __ENDTRY
2992 return ret;
2995 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
2996 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2997 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2999 BOOL ret;
3001 __TRY
3003 const CRYPT_DATA_BLOB *blob = pvStructInfo;
3004 DWORD bytesNeeded, lenBytes;
3006 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
3007 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
3009 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
3010 bytesNeeded = 1 + lenBytes + blob->cbData;
3011 if (!pbEncoded)
3013 *pcbEncoded = bytesNeeded;
3014 ret = TRUE;
3016 else
3018 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3019 pcbEncoded, bytesNeeded)))
3021 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3022 pbEncoded = *(BYTE **)pbEncoded;
3023 *pbEncoded++ = ASN_OCTETSTRING;
3024 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
3025 pbEncoded += lenBytes;
3026 if (blob->cbData)
3027 memcpy(pbEncoded, blob->pbData, blob->cbData);
3031 __EXCEPT_PAGE_FAULT
3033 SetLastError(STATUS_ACCESS_VIOLATION);
3034 ret = FALSE;
3036 __ENDTRY
3037 TRACE("returning %d (%08x)\n", ret, GetLastError());
3038 return ret;
3041 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
3042 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3043 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3045 BOOL ret;
3047 __TRY
3049 const CRYPT_BIT_BLOB *blob = pvStructInfo;
3050 DWORD bytesNeeded, lenBytes, dataBytes;
3051 BYTE unusedBits;
3053 /* yep, MS allows cUnusedBits to be >= 8 */
3054 if (!blob->cUnusedBits)
3056 dataBytes = blob->cbData;
3057 unusedBits = 0;
3059 else if (blob->cbData * 8 > blob->cUnusedBits)
3061 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
3062 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
3063 blob->cUnusedBits;
3065 else
3067 dataBytes = 0;
3068 unusedBits = 0;
3070 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
3071 bytesNeeded = 1 + lenBytes + dataBytes + 1;
3072 if (!pbEncoded)
3074 *pcbEncoded = bytesNeeded;
3075 ret = TRUE;
3077 else
3079 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3080 pcbEncoded, bytesNeeded)))
3082 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3083 pbEncoded = *(BYTE **)pbEncoded;
3084 *pbEncoded++ = ASN_BITSTRING;
3085 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
3086 pbEncoded += lenBytes;
3087 *pbEncoded++ = unusedBits;
3088 if (dataBytes)
3090 BYTE mask = 0xff << unusedBits;
3092 if (dataBytes > 1)
3094 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
3095 pbEncoded += dataBytes - 1;
3097 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
3102 __EXCEPT_PAGE_FAULT
3104 SetLastError(STATUS_ACCESS_VIOLATION);
3105 ret = FALSE;
3107 __ENDTRY
3108 return ret;
3111 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
3112 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3113 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3115 BOOL ret;
3117 __TRY
3119 const CRYPT_BIT_BLOB *blob = pvStructInfo;
3120 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
3122 ret = TRUE;
3123 if (newBlob.cbData)
3125 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
3126 if (newBlob.pbData)
3128 DWORD i;
3130 for (i = 0; i < newBlob.cbData; i++)
3131 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
3133 else
3134 ret = FALSE;
3136 if (ret)
3137 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
3138 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3139 CryptMemFree(newBlob.pbData);
3141 __EXCEPT_PAGE_FAULT
3143 SetLastError(STATUS_ACCESS_VIOLATION);
3144 ret = FALSE;
3146 __ENDTRY
3147 return ret;
3150 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
3151 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3152 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3154 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
3156 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
3157 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3160 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
3161 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3162 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3164 BOOL ret;
3166 __TRY
3168 DWORD significantBytes, lenBytes, bytesNeeded;
3169 BYTE padByte = 0;
3170 BOOL pad = FALSE;
3171 const CRYPT_INTEGER_BLOB *blob = pvStructInfo;
3173 significantBytes = blob->cbData;
3174 if (significantBytes)
3176 if (blob->pbData[significantBytes - 1] & 0x80)
3178 /* negative, lop off leading (little-endian) 0xffs */
3179 for (; significantBytes > 0 &&
3180 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
3182 if (blob->pbData[significantBytes - 1] < 0x80)
3184 padByte = 0xff;
3185 pad = TRUE;
3188 else
3190 /* positive, lop off leading (little-endian) zeroes */
3191 for (; significantBytes > 0 &&
3192 !blob->pbData[significantBytes - 1]; significantBytes--)
3194 if (significantBytes == 0)
3195 significantBytes = 1;
3196 if (blob->pbData[significantBytes - 1] > 0x7f)
3198 padByte = 0;
3199 pad = TRUE;
3203 if (pad)
3204 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3205 else
3206 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3207 bytesNeeded = 1 + lenBytes + significantBytes;
3208 if (pad)
3209 bytesNeeded++;
3210 if (!pbEncoded)
3212 *pcbEncoded = bytesNeeded;
3213 ret = TRUE;
3215 else
3217 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3218 pcbEncoded, bytesNeeded)))
3220 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3221 pbEncoded = *(BYTE **)pbEncoded;
3222 *pbEncoded++ = ASN_INTEGER;
3223 if (pad)
3225 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3226 pbEncoded += lenBytes;
3227 *pbEncoded++ = padByte;
3229 else
3231 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3232 pbEncoded += lenBytes;
3234 for (; significantBytes > 0; significantBytes--)
3235 *(pbEncoded++) = blob->pbData[significantBytes - 1];
3239 __EXCEPT_PAGE_FAULT
3241 SetLastError(STATUS_ACCESS_VIOLATION);
3242 ret = FALSE;
3244 __ENDTRY
3245 return ret;
3248 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
3249 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3250 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3252 BOOL ret;
3254 __TRY
3256 DWORD significantBytes, lenBytes, bytesNeeded;
3257 BOOL pad = FALSE;
3258 const CRYPT_INTEGER_BLOB *blob = pvStructInfo;
3260 significantBytes = blob->cbData;
3261 if (significantBytes)
3263 /* positive, lop off leading (little-endian) zeroes */
3264 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
3265 significantBytes--)
3267 if (significantBytes == 0)
3268 significantBytes = 1;
3269 if (blob->pbData[significantBytes - 1] > 0x7f)
3270 pad = TRUE;
3272 if (pad)
3273 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3274 else
3275 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3276 bytesNeeded = 1 + lenBytes + significantBytes;
3277 if (pad)
3278 bytesNeeded++;
3279 if (!pbEncoded)
3281 *pcbEncoded = bytesNeeded;
3282 ret = TRUE;
3284 else
3286 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3287 pcbEncoded, bytesNeeded)))
3289 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3290 pbEncoded = *(BYTE **)pbEncoded;
3291 *pbEncoded++ = ASN_INTEGER;
3292 if (pad)
3294 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3295 pbEncoded += lenBytes;
3296 *pbEncoded++ = 0;
3298 else
3300 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3301 pbEncoded += lenBytes;
3303 for (; significantBytes > 0; significantBytes--)
3304 *(pbEncoded++) = blob->pbData[significantBytes - 1];
3308 __EXCEPT_PAGE_FAULT
3310 SetLastError(STATUS_ACCESS_VIOLATION);
3311 ret = FALSE;
3313 __ENDTRY
3314 return ret;
3317 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
3318 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3319 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3321 CRYPT_INTEGER_BLOB blob;
3322 BOOL ret;
3324 /* Encode as an unsigned integer, then change the tag to enumerated */
3325 blob.cbData = sizeof(DWORD);
3326 blob.pbData = (BYTE *)pvStructInfo;
3327 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
3328 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3329 if (ret && pbEncoded)
3331 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3332 pbEncoded = *(BYTE **)pbEncoded;
3333 pbEncoded[0] = ASN_ENUMERATED;
3335 return ret;
3338 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
3339 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3340 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3342 BOOL ret;
3344 __TRY
3346 SYSTEMTIME sysTime;
3347 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
3348 * temporary buffer because the output buffer is not NULL-terminated.
3350 char buf[16];
3351 static const DWORD bytesNeeded = sizeof(buf) - 1;
3353 if (!pbEncoded)
3355 *pcbEncoded = bytesNeeded;
3356 ret = TRUE;
3358 else
3360 /* Sanity check the year, this is a two-digit year format */
3361 ret = FileTimeToSystemTime(pvStructInfo, &sysTime);
3362 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
3364 SetLastError(CRYPT_E_BAD_ENCODE);
3365 ret = FALSE;
3367 if (ret)
3369 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3370 pbEncoded, pcbEncoded, bytesNeeded)))
3372 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3373 pbEncoded = *(BYTE **)pbEncoded;
3374 buf[0] = ASN_UTCTIME;
3375 buf[1] = bytesNeeded - 2;
3376 snprintf(buf + 2, sizeof(buf) - 2,
3377 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
3378 sysTime.wYear - 2000 : sysTime.wYear - 1900,
3379 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3380 sysTime.wMinute, sysTime.wSecond);
3381 memcpy(pbEncoded, buf, bytesNeeded);
3386 __EXCEPT_PAGE_FAULT
3388 SetLastError(STATUS_ACCESS_VIOLATION);
3389 ret = FALSE;
3391 __ENDTRY
3392 return ret;
3395 static BOOL CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
3396 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3397 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3399 BOOL ret;
3401 __TRY
3403 SYSTEMTIME sysTime;
3404 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
3405 * temporary buffer because the output buffer is not NULL-terminated.
3407 char buf[18];
3408 static const DWORD bytesNeeded = sizeof(buf) - 1;
3410 if (!pbEncoded)
3412 *pcbEncoded = bytesNeeded;
3413 ret = TRUE;
3415 else
3417 ret = FileTimeToSystemTime(pvStructInfo, &sysTime);
3418 if (ret)
3419 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3420 pcbEncoded, bytesNeeded);
3421 if (ret)
3423 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3424 pbEncoded = *(BYTE **)pbEncoded;
3425 buf[0] = ASN_GENERALTIME;
3426 buf[1] = bytesNeeded - 2;
3427 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
3428 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3429 sysTime.wMinute, sysTime.wSecond);
3430 memcpy(pbEncoded, buf, bytesNeeded);
3434 __EXCEPT_PAGE_FAULT
3436 SetLastError(STATUS_ACCESS_VIOLATION);
3437 ret = FALSE;
3439 __ENDTRY
3440 return ret;
3443 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
3444 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3445 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3447 BOOL ret;
3449 __TRY
3451 SYSTEMTIME sysTime;
3453 /* Check the year, if it's in the UTCTime range call that encode func */
3454 if (!FileTimeToSystemTime(pvStructInfo, &sysTime))
3455 return FALSE;
3456 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
3457 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
3458 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3459 else
3460 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
3461 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
3462 pcbEncoded);
3464 __EXCEPT_PAGE_FAULT
3466 SetLastError(STATUS_ACCESS_VIOLATION);
3467 ret = FALSE;
3469 __ENDTRY
3470 return ret;
3473 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
3474 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3475 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3477 BOOL ret;
3479 __TRY
3481 DWORD bytesNeeded, dataLen, lenBytes, i;
3482 const CRYPT_SEQUENCE_OF_ANY *seq = pvStructInfo;
3484 for (i = 0, dataLen = 0; i < seq->cValue; i++)
3485 dataLen += seq->rgValue[i].cbData;
3486 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3487 bytesNeeded = 1 + lenBytes + dataLen;
3488 if (!pbEncoded)
3490 *pcbEncoded = bytesNeeded;
3491 ret = TRUE;
3493 else
3495 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3496 pcbEncoded, bytesNeeded)))
3498 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3499 pbEncoded = *(BYTE **)pbEncoded;
3500 *pbEncoded++ = ASN_SEQUENCEOF;
3501 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
3502 pbEncoded += lenBytes;
3503 for (i = 0; i < seq->cValue; i++)
3505 memcpy(pbEncoded, seq->rgValue[i].pbData,
3506 seq->rgValue[i].cbData);
3507 pbEncoded += seq->rgValue[i].cbData;
3512 __EXCEPT_PAGE_FAULT
3514 SetLastError(STATUS_ACCESS_VIOLATION);
3515 ret = FALSE;
3517 __ENDTRY
3518 return ret;
3521 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
3522 BYTE *pbEncoded, DWORD *pcbEncoded)
3524 BOOL ret = TRUE;
3525 struct AsnEncodeSequenceItem items[3] = { { 0 } };
3526 struct AsnConstructedItem constructed = { 0 };
3527 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
3528 DWORD cItem = 0, cSwapped = 0;
3530 switch (distPoint->DistPointName.dwDistPointNameChoice)
3532 case CRL_DIST_POINT_NO_NAME:
3533 /* do nothing */
3534 break;
3535 case CRL_DIST_POINT_FULL_NAME:
3536 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3537 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
3538 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3539 constructed.tag = 0;
3540 constructed.pvStructInfo = &swapped[cSwapped];
3541 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3542 items[cItem].pvStructInfo = &constructed;
3543 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3544 cSwapped++;
3545 cItem++;
3546 break;
3547 case CRL_DIST_POINT_ISSUER_RDN_NAME:
3548 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3549 ret = FALSE;
3550 break;
3551 default:
3552 ret = FALSE;
3554 if (ret && distPoint->ReasonFlags.cbData)
3556 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3557 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
3558 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3559 items[cItem].pvStructInfo = &swapped[cSwapped];
3560 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3561 cSwapped++;
3562 cItem++;
3564 if (ret && distPoint->CRLIssuer.cAltEntry)
3566 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
3567 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
3568 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3569 items[cItem].pvStructInfo = &swapped[cSwapped];
3570 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3571 cSwapped++;
3572 cItem++;
3574 if (ret)
3575 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
3576 pbEncoded, pcbEncoded);
3577 return ret;
3580 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
3581 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3582 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3584 BOOL ret;
3586 __TRY
3588 const CRL_DIST_POINTS_INFO *info = pvStructInfo;
3590 if (!info->cDistPoint)
3592 SetLastError(E_INVALIDARG);
3593 ret = FALSE;
3595 else
3597 DWORD bytesNeeded, dataLen, lenBytes, i;
3599 ret = TRUE;
3600 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
3602 DWORD len;
3604 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
3605 &len);
3606 if (ret)
3607 dataLen += len;
3608 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
3610 /* Have to propagate index of failing character */
3611 *pcbEncoded = len;
3614 if (ret)
3616 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3617 bytesNeeded = 1 + lenBytes + dataLen;
3618 if (!pbEncoded)
3620 *pcbEncoded = bytesNeeded;
3621 ret = TRUE;
3623 else
3625 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3626 pbEncoded, pcbEncoded, bytesNeeded)))
3628 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3629 pbEncoded = *(BYTE **)pbEncoded;
3630 *pbEncoded++ = ASN_SEQUENCEOF;
3631 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
3632 pbEncoded += lenBytes;
3633 for (i = 0; ret && i < info->cDistPoint; i++)
3635 DWORD len = dataLen;
3637 ret = CRYPT_AsnEncodeDistPoint(
3638 &info->rgDistPoint[i], pbEncoded, &len);
3639 if (ret)
3641 pbEncoded += len;
3642 dataLen -= len;
3650 __EXCEPT_PAGE_FAULT
3652 SetLastError(STATUS_ACCESS_VIOLATION);
3653 ret = FALSE;
3655 __ENDTRY
3656 return ret;
3659 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3660 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3661 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3663 BOOL ret;
3665 __TRY
3667 const CERT_ENHKEY_USAGE *usage = pvStructInfo;
3668 DWORD bytesNeeded = 0, lenBytes, size, i;
3670 ret = TRUE;
3671 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3673 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3674 usage->rgpszUsageIdentifier[i],
3675 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
3676 if (ret)
3677 bytesNeeded += size;
3679 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3680 bytesNeeded += 1 + lenBytes;
3681 if (ret)
3683 if (!pbEncoded)
3684 *pcbEncoded = bytesNeeded;
3685 else
3687 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3688 pbEncoded, pcbEncoded, bytesNeeded)))
3690 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3691 pbEncoded = *(BYTE **)pbEncoded;
3692 *pbEncoded++ = ASN_SEQUENCEOF;
3693 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
3694 &lenBytes);
3695 pbEncoded += lenBytes;
3696 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3698 size = bytesNeeded;
3699 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3700 usage->rgpszUsageIdentifier[i],
3701 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
3702 &size);
3703 if (ret)
3705 pbEncoded += size;
3706 bytesNeeded -= size;
3713 __EXCEPT_PAGE_FAULT
3715 SetLastError(STATUS_ACCESS_VIOLATION);
3716 ret = FALSE;
3718 __ENDTRY
3719 return ret;
3722 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
3723 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3724 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3726 BOOL ret;
3728 __TRY
3730 const CRL_ISSUING_DIST_POINT *point = pvStructInfo;
3731 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3732 struct AsnConstructedItem constructed = { 0 };
3733 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3734 DWORD cItem = 0, cSwapped = 0;
3736 ret = TRUE;
3737 switch (point->DistPointName.dwDistPointNameChoice)
3739 case CRL_DIST_POINT_NO_NAME:
3740 /* do nothing */
3741 break;
3742 case CRL_DIST_POINT_FULL_NAME:
3743 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3744 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3745 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3746 constructed.tag = 0;
3747 constructed.pvStructInfo = &swapped[cSwapped];
3748 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3749 items[cItem].pvStructInfo = &constructed;
3750 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3751 cSwapped++;
3752 cItem++;
3753 break;
3754 default:
3755 SetLastError(E_INVALIDARG);
3756 ret = FALSE;
3758 if (ret && point->fOnlyContainsUserCerts)
3760 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3761 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3762 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3763 items[cItem].pvStructInfo = &swapped[cSwapped];
3764 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3765 cSwapped++;
3766 cItem++;
3768 if (ret && point->fOnlyContainsCACerts)
3770 swapped[cSwapped].tag = ASN_CONTEXT | 2;
3771 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3772 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3773 items[cItem].pvStructInfo = &swapped[cSwapped];
3774 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3775 cSwapped++;
3776 cItem++;
3778 if (ret && point->OnlySomeReasonFlags.cbData)
3780 swapped[cSwapped].tag = ASN_CONTEXT | 3;
3781 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3782 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3783 items[cItem].pvStructInfo = &swapped[cSwapped];
3784 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3785 cSwapped++;
3786 cItem++;
3788 if (ret && point->fIndirectCRL)
3790 swapped[cSwapped].tag = ASN_CONTEXT | 4;
3791 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
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)
3799 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3800 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3802 __EXCEPT_PAGE_FAULT
3804 SetLastError(STATUS_ACCESS_VIOLATION);
3805 ret = FALSE;
3807 __ENDTRY
3808 return ret;
3811 static BOOL CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType,
3812 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3813 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3815 BOOL ret;
3816 const CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
3817 struct AsnEncodeSequenceItem items[3] = {
3818 { &subtree->Base, CRYPT_AsnEncodeAltNameEntry, 0 },
3819 { 0 }
3821 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3822 DWORD cItem = 1, cSwapped = 0;
3824 if (subtree->dwMinimum)
3826 swapped[cSwapped].tag = ASN_CONTEXT | 0;
3827 swapped[cSwapped].pvStructInfo = &subtree->dwMinimum;
3828 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3829 items[cItem].pvStructInfo = &swapped[cSwapped];
3830 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3831 cSwapped++;
3832 cItem++;
3834 if (subtree->fMaximum)
3836 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3837 swapped[cSwapped].pvStructInfo = &subtree->dwMaximum;
3838 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3839 items[cItem].pvStructInfo = &swapped[cSwapped];
3840 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3841 cSwapped++;
3842 cItem++;
3844 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags,
3845 pEncodePara, pbEncoded, pcbEncoded);
3846 return ret;
3849 static BOOL WINAPI CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType,
3850 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3851 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3853 BOOL ret = FALSE;
3854 CRYPT_BLOB_ARRAY permitted = { 0, NULL }, excluded = { 0, NULL };
3856 TRACE("%p\n", pvStructInfo);
3858 __TRY
3860 const CERT_NAME_CONSTRAINTS_INFO *constraints = pvStructInfo;
3861 struct AsnEncodeSequenceItem items[2] = { { 0 } };
3862 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3863 DWORD i, cItem = 0, cSwapped = 0;
3865 ret = TRUE;
3866 if (constraints->cPermittedSubtree)
3868 permitted.rgBlob = CryptMemAlloc(
3869 constraints->cPermittedSubtree * sizeof(CRYPT_DER_BLOB));
3870 if (permitted.rgBlob)
3872 permitted.cBlob = constraints->cPermittedSubtree;
3873 memset(permitted.rgBlob, 0,
3874 permitted.cBlob * sizeof(CRYPT_DER_BLOB));
3875 for (i = 0; ret && i < permitted.cBlob; i++)
3876 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3877 NULL, &constraints->rgPermittedSubtree[i],
3878 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3879 (BYTE *)&permitted.rgBlob[i].pbData,
3880 &permitted.rgBlob[i].cbData);
3881 if (ret)
3883 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3884 swapped[cSwapped].pvStructInfo = &permitted;
3885 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3886 items[cItem].pvStructInfo = &swapped[cSwapped];
3887 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3888 cSwapped++;
3889 cItem++;
3892 else
3893 ret = FALSE;
3895 if (constraints->cExcludedSubtree)
3897 excluded.rgBlob = CryptMemAlloc(
3898 constraints->cExcludedSubtree * sizeof(CRYPT_DER_BLOB));
3899 if (excluded.rgBlob)
3901 excluded.cBlob = constraints->cExcludedSubtree;
3902 memset(excluded.rgBlob, 0,
3903 excluded.cBlob * sizeof(CRYPT_DER_BLOB));
3904 for (i = 0; ret && i < excluded.cBlob; i++)
3905 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3906 NULL, &constraints->rgExcludedSubtree[i],
3907 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3908 (BYTE *)&excluded.rgBlob[i].pbData,
3909 &excluded.rgBlob[i].cbData);
3910 if (ret)
3912 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
3913 swapped[cSwapped].pvStructInfo = &excluded;
3914 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3915 items[cItem].pvStructInfo = &swapped[cSwapped];
3916 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3917 cSwapped++;
3918 cItem++;
3921 else
3922 ret = FALSE;
3924 if (ret)
3925 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3926 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3927 for (i = 0; i < permitted.cBlob; i++)
3928 LocalFree(permitted.rgBlob[i].pbData);
3929 for (i = 0; i < excluded.cBlob; i++)
3930 LocalFree(excluded.rgBlob[i].pbData);
3932 __EXCEPT_PAGE_FAULT
3934 SetLastError(STATUS_ACCESS_VIOLATION);
3936 __ENDTRY
3937 CryptMemFree(permitted.rgBlob);
3938 CryptMemFree(excluded.rgBlob);
3939 TRACE("returning %d\n", ret);
3940 return ret;
3943 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
3944 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3945 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3946 DWORD *pcbEncoded)
3948 BOOL ret;
3949 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
3950 struct AsnEncodeSequenceItem items[] = {
3951 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
3952 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
3955 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3956 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3957 pcbEncoded);
3958 return ret;
3961 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
3962 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3963 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3965 BOOL ret = FALSE;
3967 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
3969 SetLastError(E_INVALIDARG);
3970 return FALSE;
3973 __TRY
3975 const CMSG_SIGNER_INFO *info = pvStructInfo;
3977 if (!info->Issuer.cbData)
3978 SetLastError(E_INVALIDARG);
3979 else
3981 struct AsnEncodeSequenceItem items[7] = {
3982 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
3983 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
3984 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
3985 0 },
3987 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3988 DWORD cItem = 3, cSwapped = 0;
3990 if (info->AuthAttrs.cAttr)
3992 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3993 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
3994 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3995 items[cItem].pvStructInfo = &swapped[cSwapped];
3996 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3997 cSwapped++;
3998 cItem++;
4000 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
4001 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4002 cItem++;
4003 items[cItem].pvStructInfo = &info->EncryptedHash;
4004 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
4005 cItem++;
4006 if (info->UnauthAttrs.cAttr)
4008 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4009 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
4010 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4011 items[cItem].pvStructInfo = &swapped[cSwapped];
4012 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4013 cSwapped++;
4014 cItem++;
4016 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4017 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4020 __EXCEPT_PAGE_FAULT
4022 SetLastError(STATUS_ACCESS_VIOLATION);
4024 __ENDTRY
4025 return ret;
4028 static BOOL WINAPI CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType,
4029 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4030 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4032 BOOL ret = FALSE;
4034 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
4036 SetLastError(E_INVALIDARG);
4037 return FALSE;
4040 __TRY
4042 const CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
4044 if (info->SignerId.dwIdChoice != CERT_ID_ISSUER_SERIAL_NUMBER &&
4045 info->SignerId.dwIdChoice != CERT_ID_KEY_IDENTIFIER)
4046 SetLastError(E_INVALIDARG);
4047 else if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER &&
4048 !info->SignerId.u.IssuerSerialNumber.Issuer.cbData)
4049 SetLastError(E_INVALIDARG);
4050 else
4052 struct AsnEncodeSequenceItem items[7] = {
4053 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4055 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
4056 DWORD cItem = 1, cSwapped = 0;
4058 if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
4060 items[cItem].pvStructInfo =
4061 &info->SignerId.u.IssuerSerialNumber.Issuer;
4062 items[cItem].encodeFunc =
4063 CRYPT_AsnEncodeIssuerSerialNumber;
4064 cItem++;
4066 else
4068 swapped[cSwapped].tag = ASN_CONTEXT | 0;
4069 swapped[cSwapped].pvStructInfo = &info->SignerId.u.KeyId;
4070 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
4071 items[cItem].pvStructInfo = &swapped[cSwapped];
4072 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4073 cSwapped++;
4074 cItem++;
4076 items[cItem].pvStructInfo = &info->HashAlgorithm;
4077 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4078 cItem++;
4079 if (info->AuthAttrs.cAttr)
4081 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4082 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
4083 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4084 items[cItem].pvStructInfo = &swapped[cSwapped];
4085 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4086 cSwapped++;
4087 cItem++;
4089 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
4090 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4091 cItem++;
4092 items[cItem].pvStructInfo = &info->EncryptedHash;
4093 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
4094 cItem++;
4095 if (info->UnauthAttrs.cAttr)
4097 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4098 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
4099 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4100 items[cItem].pvStructInfo = &swapped[cSwapped];
4101 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4102 cSwapped++;
4103 cItem++;
4105 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4106 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4109 __EXCEPT_PAGE_FAULT
4111 SetLastError(STATUS_ACCESS_VIOLATION);
4113 __ENDTRY
4114 return ret;
4117 BOOL CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
4118 DWORD *pcbData)
4120 struct AsnEncodeSequenceItem items[7] = {
4121 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
4123 struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 };
4124 struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 };
4125 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4126 DWORD cItem = 1, cSwapped = 0;
4127 BOOL ret = TRUE;
4129 if (signedInfo->cSignerInfo)
4131 digestAlgorithmsSet.cItems = signedInfo->cSignerInfo;
4132 digestAlgorithmsSet.items = signedInfo->rgSignerInfo;
4133 digestAlgorithmsSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
4134 digestAlgorithmsSet.itemOffset =
4135 offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm);
4136 digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4137 items[cItem].pvStructInfo = &digestAlgorithmsSet;
4138 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4139 cItem++;
4141 items[cItem].pvStructInfo = &signedInfo->content;
4142 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal;
4143 cItem++;
4144 if (signedInfo->cCertEncoded)
4146 certSet.cItems = signedInfo->cCertEncoded;
4147 certSet.items = signedInfo->rgCertEncoded;
4148 certSet.itemSize = sizeof(CERT_BLOB);
4149 certSet.itemOffset = 0;
4150 certSet.encode = CRYPT_CopyEncodedBlob;
4151 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0;
4152 swapped[cSwapped].pvStructInfo = &certSet;
4153 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4154 items[cItem].pvStructInfo = &swapped[cSwapped];
4155 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4156 cSwapped++;
4157 cItem++;
4159 if (signedInfo->cCrlEncoded)
4161 crlSet.cItems = signedInfo->cCrlEncoded;
4162 crlSet.items = signedInfo->rgCrlEncoded;
4163 crlSet.itemSize = sizeof(CRL_BLOB);
4164 crlSet.itemOffset = 0;
4165 crlSet.encode = CRYPT_CopyEncodedBlob;
4166 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
4167 swapped[cSwapped].pvStructInfo = &crlSet;
4168 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4169 items[cItem].pvStructInfo = &swapped[cSwapped];
4170 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4171 cSwapped++;
4172 cItem++;
4174 if (ret && signedInfo->cSignerInfo)
4176 signerSet.cItems = signedInfo->cSignerInfo;
4177 signerSet.items = signedInfo->rgSignerInfo;
4178 signerSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
4179 signerSet.itemOffset = 0;
4180 signerSet.encode = CRYPT_AsnEncodeCMSSignerInfo;
4181 items[cItem].pvStructInfo = &signerSet;
4182 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4183 cItem++;
4185 if (ret)
4186 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
4187 items, cItem, 0, NULL, pvData, pcbData);
4189 return ret;
4192 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
4193 LPCSTR lpszStructType)
4195 CryptEncodeObjectExFunc encodeFunc = NULL;
4197 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4198 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4200 SetLastError(ERROR_FILE_NOT_FOUND);
4201 return NULL;
4204 if (!HIWORD(lpszStructType))
4206 switch (LOWORD(lpszStructType))
4208 case LOWORD(X509_CERT):
4209 encodeFunc = CRYPT_AsnEncodeCert;
4210 break;
4211 case LOWORD(X509_CERT_TO_BE_SIGNED):
4212 encodeFunc = CRYPT_AsnEncodeCertInfo;
4213 break;
4214 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
4215 encodeFunc = CRYPT_AsnEncodeCRLInfo;
4216 break;
4217 case LOWORD(X509_EXTENSIONS):
4218 encodeFunc = CRYPT_AsnEncodeExtensions;
4219 break;
4220 case LOWORD(X509_NAME_VALUE):
4221 encodeFunc = CRYPT_AsnEncodeNameValue;
4222 break;
4223 case LOWORD(X509_NAME):
4224 encodeFunc = CRYPT_AsnEncodeName;
4225 break;
4226 case LOWORD(X509_PUBLIC_KEY_INFO):
4227 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
4228 break;
4229 case LOWORD(X509_AUTHORITY_KEY_ID):
4230 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
4231 break;
4232 case LOWORD(X509_ALTERNATE_NAME):
4233 encodeFunc = CRYPT_AsnEncodeAltName;
4234 break;
4235 case LOWORD(X509_BASIC_CONSTRAINTS):
4236 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
4237 break;
4238 case LOWORD(X509_BASIC_CONSTRAINTS2):
4239 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
4240 break;
4241 case LOWORD(X509_CERT_POLICIES):
4242 encodeFunc = CRYPT_AsnEncodeCertPolicies;
4243 break;
4244 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
4245 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
4246 break;
4247 case LOWORD(X509_UNICODE_NAME):
4248 encodeFunc = CRYPT_AsnEncodeUnicodeName;
4249 break;
4250 case LOWORD(PKCS_CONTENT_INFO):
4251 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
4252 break;
4253 case LOWORD(PKCS_ATTRIBUTE):
4254 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
4255 break;
4256 case LOWORD(X509_UNICODE_NAME_VALUE):
4257 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
4258 break;
4259 case LOWORD(X509_OCTET_STRING):
4260 encodeFunc = CRYPT_AsnEncodeOctets;
4261 break;
4262 case LOWORD(X509_BITS):
4263 case LOWORD(X509_KEY_USAGE):
4264 encodeFunc = CRYPT_AsnEncodeBits;
4265 break;
4266 case LOWORD(X509_INTEGER):
4267 encodeFunc = CRYPT_AsnEncodeInt;
4268 break;
4269 case LOWORD(X509_MULTI_BYTE_INTEGER):
4270 encodeFunc = CRYPT_AsnEncodeInteger;
4271 break;
4272 case LOWORD(X509_MULTI_BYTE_UINT):
4273 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
4274 break;
4275 case LOWORD(X509_ENUMERATED):
4276 encodeFunc = CRYPT_AsnEncodeEnumerated;
4277 break;
4278 case LOWORD(X509_CHOICE_OF_TIME):
4279 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
4280 break;
4281 case LOWORD(X509_AUTHORITY_KEY_ID2):
4282 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
4283 break;
4284 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
4285 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
4286 break;
4287 case LOWORD(X509_SEQUENCE_OF_ANY):
4288 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
4289 break;
4290 case LOWORD(PKCS_UTC_TIME):
4291 encodeFunc = CRYPT_AsnEncodeUtcTime;
4292 break;
4293 case LOWORD(X509_CRL_DIST_POINTS):
4294 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
4295 break;
4296 case LOWORD(X509_ENHANCED_KEY_USAGE):
4297 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
4298 break;
4299 case LOWORD(PKCS_CTL):
4300 encodeFunc = CRYPT_AsnEncodeCTL;
4301 break;
4302 case LOWORD(PKCS_SMIME_CAPABILITIES):
4303 encodeFunc = CRYPT_AsnEncodeSMIMECapabilities;
4304 break;
4305 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
4306 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
4307 break;
4308 case LOWORD(PKCS_ATTRIBUTES):
4309 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4310 break;
4311 case LOWORD(X509_ISSUING_DIST_POINT):
4312 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
4313 break;
4314 case LOWORD(X509_NAME_CONSTRAINTS):
4315 encodeFunc = CRYPT_AsnEncodeNameConstraints;
4316 break;
4317 case LOWORD(PKCS7_SIGNER_INFO):
4318 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
4319 break;
4320 case LOWORD(CMS_SIGNER_INFO):
4321 encodeFunc = CRYPT_AsnEncodeCMSSignerInfo;
4322 break;
4325 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4326 encodeFunc = CRYPT_AsnEncodeExtensions;
4327 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4328 encodeFunc = CRYPT_AsnEncodeUtcTime;
4329 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
4330 encodeFunc = CRYPT_AsnEncodeUtcTime;
4331 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4332 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
4333 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4334 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
4335 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4336 encodeFunc = CRYPT_AsnEncodeEnumerated;
4337 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4338 encodeFunc = CRYPT_AsnEncodeBits;
4339 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4340 encodeFunc = CRYPT_AsnEncodeOctets;
4341 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4342 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
4343 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4344 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
4345 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4346 encodeFunc = CRYPT_AsnEncodeAltName;
4347 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4348 encodeFunc = CRYPT_AsnEncodeAltName;
4349 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4350 encodeFunc = CRYPT_AsnEncodeAltName;
4351 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4352 encodeFunc = CRYPT_AsnEncodeAltName;
4353 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4354 encodeFunc = CRYPT_AsnEncodeAltName;
4355 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4356 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
4357 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
4358 encodeFunc = CRYPT_AsnEncodeCertPolicies;
4359 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4360 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
4361 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4362 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
4363 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
4364 encodeFunc = CRYPT_AsnEncodeNameConstraints;
4365 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
4366 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
4367 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
4368 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
4369 else if (!strcmp(lpszStructType, szOID_CTL))
4370 encodeFunc = CRYPT_AsnEncodeCTL;
4371 return encodeFunc;
4374 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType,
4375 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4377 static HCRYPTOIDFUNCSET set = NULL;
4378 CryptEncodeObjectFunc encodeFunc = NULL;
4380 if (!set)
4381 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
4382 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4383 (void **)&encodeFunc, hFunc);
4384 return encodeFunc;
4387 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType,
4388 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4390 static HCRYPTOIDFUNCSET set = NULL;
4391 CryptEncodeObjectExFunc encodeFunc = NULL;
4393 if (!set)
4394 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
4395 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4396 (void **)&encodeFunc, hFunc);
4397 return encodeFunc;
4400 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4401 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
4403 BOOL ret = FALSE;
4404 HCRYPTOIDFUNCADDR hFunc = NULL;
4405 CryptEncodeObjectFunc pCryptEncodeObject = NULL;
4406 CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL;
4408 TRACE_(crypt)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
4409 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
4410 pcbEncoded);
4412 if (!pbEncoded && !pcbEncoded)
4414 SetLastError(ERROR_INVALID_PARAMETER);
4415 return FALSE;
4418 if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType,
4419 lpszStructType)))
4421 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4422 debugstr_a(lpszStructType));
4423 pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType,
4424 lpszStructType, &hFunc);
4425 if (!pCryptEncodeObject)
4426 pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType,
4427 lpszStructType, &hFunc);
4429 if (pCryptEncodeObject)
4430 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4431 pvStructInfo, pbEncoded, pcbEncoded);
4432 else if (pCryptEncodeObjectEx)
4433 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
4434 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
4435 if (hFunc)
4436 CryptFreeOIDFunctionAddress(hFunc, 0);
4437 TRACE_(crypt)("returning %d\n", ret);
4438 return ret;
4441 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4442 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
4443 void *pvEncoded, DWORD *pcbEncoded)
4445 BOOL ret = FALSE;
4446 HCRYPTOIDFUNCADDR hFunc = NULL;
4447 CryptEncodeObjectExFunc encodeFunc = NULL;
4449 TRACE_(crypt)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
4450 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
4451 pvEncoded, pcbEncoded);
4453 if (!pvEncoded && !pcbEncoded)
4455 SetLastError(ERROR_INVALID_PARAMETER);
4456 return FALSE;
4459 SetLastError(NOERROR);
4460 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
4461 *(BYTE **)pvEncoded = NULL;
4462 encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType);
4463 if (!encodeFunc)
4465 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4466 debugstr_a(lpszStructType));
4467 encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType,
4468 &hFunc);
4470 if (encodeFunc)
4471 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
4472 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
4473 else
4475 CryptEncodeObjectFunc pCryptEncodeObject =
4476 CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4478 if (pCryptEncodeObject)
4480 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
4482 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4483 pvStructInfo, NULL, pcbEncoded);
4484 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
4485 pvEncoded, pcbEncoded, *pcbEncoded)))
4486 ret = pCryptEncodeObject(dwCertEncodingType,
4487 lpszStructType, pvStructInfo, *(BYTE **)pvEncoded,
4488 pcbEncoded);
4490 else
4491 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4492 pvStructInfo, pvEncoded, pcbEncoded);
4495 if (hFunc)
4496 CryptFreeOIDFunctionAddress(hFunc, 0);
4497 TRACE_(crypt)("returning %d\n", ret);
4498 return ret;
4501 BOOL WINAPI PFXExportCertStore(HCERTSTORE hStore, CRYPT_DATA_BLOB *pPFX,
4502 LPCWSTR szPassword, DWORD dwFlags)
4504 return PFXExportCertStoreEx(hStore, pPFX, szPassword, NULL, dwFlags);
4507 BOOL WINAPI PFXExportCertStoreEx(HCERTSTORE hStore, CRYPT_DATA_BLOB *pPFX,
4508 LPCWSTR szPassword, void *pvReserved, DWORD dwFlags)
4510 FIXME_(crypt)("(%p, %p, %p, %p, %08x): stub\n", hStore, pPFX, szPassword,
4511 pvReserved, dwFlags);
4512 return FALSE;
4515 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
4516 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4518 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
4519 NULL, 0, NULL, pInfo, pcbInfo);
4522 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
4523 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
4524 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4526 BOOL ret;
4527 HCRYPTKEY key;
4528 static CHAR oid[] = szOID_RSA_RSA;
4530 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
4531 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
4532 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
4534 if (!pszPublicKeyObjId)
4535 pszPublicKeyObjId = oid;
4536 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
4538 DWORD keySize = 0;
4540 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
4541 if (ret)
4543 LPBYTE pubKey = CryptMemAlloc(keySize);
4545 if (pubKey)
4547 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
4548 &keySize);
4549 if (ret)
4551 DWORD encodedLen = 0;
4553 ret = CryptEncodeObject(dwCertEncodingType,
4554 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
4555 if (ret)
4557 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
4558 strlen(pszPublicKeyObjId) + 1 + encodedLen;
4560 if (!pInfo)
4561 *pcbInfo = sizeNeeded;
4562 else if (*pcbInfo < sizeNeeded)
4564 SetLastError(ERROR_MORE_DATA);
4565 *pcbInfo = sizeNeeded;
4566 ret = FALSE;
4568 else
4570 pInfo->Algorithm.pszObjId = (char *)pInfo +
4571 sizeof(CERT_PUBLIC_KEY_INFO);
4572 lstrcpyA(pInfo->Algorithm.pszObjId,
4573 pszPublicKeyObjId);
4574 pInfo->Algorithm.Parameters.cbData = 0;
4575 pInfo->Algorithm.Parameters.pbData = NULL;
4576 pInfo->PublicKey.pbData =
4577 (BYTE *)pInfo->Algorithm.pszObjId
4578 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
4579 pInfo->PublicKey.cbData = encodedLen;
4580 pInfo->PublicKey.cUnusedBits = 0;
4581 ret = CryptEncodeObject(dwCertEncodingType,
4582 RSA_CSP_PUBLICKEYBLOB, pubKey,
4583 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
4587 CryptMemFree(pubKey);
4589 else
4590 ret = FALSE;
4592 CryptDestroyKey(key);
4594 return ret;
4597 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
4598 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
4599 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
4601 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
4602 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
4603 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4605 static HCRYPTOIDFUNCSET set = NULL;
4606 BOOL ret;
4607 ExportPublicKeyInfoExFunc exportFunc = NULL;
4608 HCRYPTOIDFUNCADDR hFunc = NULL;
4610 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
4611 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
4612 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
4614 if (!hCryptProv)
4616 SetLastError(ERROR_INVALID_PARAMETER);
4617 return FALSE;
4620 if (pszPublicKeyObjId)
4622 if (!set)
4623 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
4625 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
4626 0, (void **)&exportFunc, &hFunc);
4628 if (!exportFunc)
4629 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
4630 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
4631 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
4632 if (hFunc)
4633 CryptFreeOIDFunctionAddress(hFunc, 0);
4634 return ret;
4637 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
4638 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
4640 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
4641 0, 0, NULL, phKey);
4644 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
4645 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4646 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
4648 BOOL ret;
4649 DWORD pubKeySize = 0;
4651 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
4652 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
4654 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
4655 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
4656 if (ret)
4658 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
4660 if (pubKey)
4662 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
4663 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
4664 &pubKeySize);
4665 if (ret)
4667 if(aiKeyAlg)
4668 ((BLOBHEADER*)pubKey)->aiKeyAlg = aiKeyAlg;
4669 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
4670 phKey);
4672 CryptMemFree(pubKey);
4674 else
4675 ret = FALSE;
4677 return ret;
4680 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
4681 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4682 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
4684 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
4685 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4686 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
4688 static HCRYPTOIDFUNCSET set = NULL;
4689 BOOL ret;
4690 ImportPublicKeyInfoExFunc importFunc = NULL;
4691 HCRYPTOIDFUNCADDR hFunc = NULL;
4693 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
4694 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
4696 if (!set)
4697 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
4698 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
4699 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
4700 if (!importFunc)
4701 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
4702 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
4703 pvAuxInfo, phKey);
4704 if (hFunc)
4705 CryptFreeOIDFunctionAddress(hFunc, 0);
4706 return ret;