winmm/tests: Add tests for visibility of video window.
[wine.git] / dlls / crypt32 / encode.c
blob8086ad2fc0a2d304a282968e54826543d72b5dbd
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 <assert.h>
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <stdlib.h>
38 #define NONAMELESSUNION
40 #include "windef.h"
41 #include "winbase.h"
42 #include "wincrypt.h"
43 #include "snmp.h"
44 #include "wine/debug.h"
45 #include "wine/exception.h"
46 #include "crypt32_private.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
49 WINE_DECLARE_DEBUG_CHANNEL(crypt);
51 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
52 BYTE *, DWORD *);
54 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
55 * The dwCertEncodingType and lpszStructType are ignored by the built-in
56 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
57 * since it must call functions in external DLLs that follow these signatures.
59 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
60 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
61 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
62 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
63 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
64 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
65 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
66 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
67 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
68 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
69 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
70 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
71 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
72 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
73 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
74 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
75 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
76 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
77 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
78 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
79 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
80 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
81 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
82 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
83 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
84 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
85 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
86 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
87 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
88 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
89 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
90 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
91 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
92 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
93 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
94 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
95 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
96 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
97 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
99 BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara,
100 BYTE *pbEncoded, DWORD *pcbEncoded, DWORD bytesNeeded)
102 BOOL ret = TRUE;
104 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
106 if (pEncodePara && pEncodePara->pfnAlloc)
107 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
108 else
109 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
110 if (!*(BYTE **)pbEncoded)
111 ret = FALSE;
112 else
113 *pcbEncoded = bytesNeeded;
115 else if (bytesNeeded > *pcbEncoded)
117 *pcbEncoded = bytesNeeded;
118 SetLastError(ERROR_MORE_DATA);
119 ret = FALSE;
121 else
122 *pcbEncoded = bytesNeeded;
123 return ret;
126 static void CRYPT_FreeSpace(const CRYPT_ENCODE_PARA *pEncodePara, LPVOID pv)
128 if (pEncodePara && pEncodePara->pfnFree)
129 pEncodePara->pfnFree(pv);
130 else
131 LocalFree(pv);
134 BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
136 DWORD bytesNeeded, significantBytes = 0;
138 if (len <= 0x7f)
139 bytesNeeded = 1;
140 else
142 DWORD temp;
144 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
145 temp <<= 8, significantBytes--)
147 bytesNeeded = significantBytes + 1;
149 if (!pbEncoded)
151 *pcbEncoded = bytesNeeded;
152 return TRUE;
154 if (*pcbEncoded < bytesNeeded)
156 SetLastError(ERROR_MORE_DATA);
157 return FALSE;
159 if (len <= 0x7f)
160 *pbEncoded = (BYTE)len;
161 else
163 DWORD i;
165 *pbEncoded++ = significantBytes | 0x80;
166 for (i = 0; i < significantBytes; i++)
168 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
169 len >>= 8;
172 *pcbEncoded = bytesNeeded;
173 return TRUE;
176 BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
177 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
178 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
180 BOOL ret;
181 DWORD i, dataLen = 0;
183 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", items, cItem, dwFlags, pEncodePara,
184 pbEncoded, pbEncoded ? *pcbEncoded : 0);
185 for (i = 0, ret = TRUE; ret && i < cItem; i++)
187 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
188 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
189 NULL, &items[i].size);
190 /* Some functions propagate their errors through the size */
191 if (!ret)
192 *pcbEncoded = items[i].size;
193 dataLen += items[i].size;
195 if (ret)
197 DWORD lenBytes, bytesNeeded;
199 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
200 bytesNeeded = 1 + lenBytes + dataLen;
201 if (!pbEncoded)
202 *pcbEncoded = bytesNeeded;
203 else
205 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
206 pcbEncoded, bytesNeeded)))
208 BYTE *out;
210 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
211 pbEncoded = *(BYTE **)pbEncoded;
212 out = pbEncoded;
213 *out++ = ASN_SEQUENCE;
214 CRYPT_EncodeLen(dataLen, out, &lenBytes);
215 out += lenBytes;
216 for (i = 0; ret && i < cItem; i++)
218 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
219 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
220 NULL, out, &items[i].size);
221 /* Some functions propagate their errors through the size */
222 if (!ret)
223 *pcbEncoded = items[i].size;
224 out += items[i].size;
226 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
227 CRYPT_FreeSpace(pEncodePara, pbEncoded);
231 TRACE("returning %d (%08lx)\n", ret, GetLastError());
232 return ret;
235 BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
236 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
237 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
239 BOOL ret;
240 const struct AsnConstructedItem *item = pvStructInfo;
241 DWORD len;
243 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
244 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
246 DWORD dataLen, bytesNeeded;
248 CRYPT_EncodeLen(len, NULL, &dataLen);
249 bytesNeeded = 1 + dataLen + len;
250 if (!pbEncoded)
251 *pcbEncoded = bytesNeeded;
252 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
253 pbEncoded, pcbEncoded, bytesNeeded)))
255 BYTE *out;
257 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
258 pbEncoded = *(BYTE **)pbEncoded;
259 out = pbEncoded;
260 *out++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
261 CRYPT_EncodeLen(len, out, &dataLen);
262 out += dataLen;
263 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
264 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
265 out, &len);
266 if (!ret)
268 /* Some functions propagate their errors through the size */
269 *pcbEncoded = len;
270 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
271 CRYPT_FreeSpace(pEncodePara, pbEncoded);
275 else
277 /* Some functions propagate their errors through the size */
278 *pcbEncoded = len;
280 return ret;
283 struct AsnEncodeTagSwappedItem
285 BYTE tag;
286 const void *pvStructInfo;
287 CryptEncodeObjectExFunc encodeFunc;
290 /* Sort of a wacky hack, it encodes something using the struct
291 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
292 * given in the struct AsnEncodeTagSwappedItem.
294 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
295 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
296 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
298 BOOL ret;
299 const struct AsnEncodeTagSwappedItem *item = pvStructInfo;
301 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
302 item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
303 if (ret && pbEncoded)
304 *pbEncoded = item->tag;
305 return ret;
308 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
309 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
310 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
312 const DWORD *ver = pvStructInfo;
313 BOOL ret;
315 /* CERT_V1 is not encoded */
316 if (*ver == CERT_V1)
318 *pcbEncoded = 0;
319 ret = TRUE;
321 else
323 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
325 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
326 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
328 return ret;
331 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
332 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
333 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
335 const CRYPT_DER_BLOB *blob = pvStructInfo;
336 BOOL ret;
338 if (!pbEncoded)
340 *pcbEncoded = blob->cbData;
341 ret = TRUE;
343 else
345 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
346 pcbEncoded, blob->cbData)))
348 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
349 pbEncoded = *(BYTE **)pbEncoded;
350 if (blob->cbData)
351 memcpy(pbEncoded, blob->pbData, blob->cbData);
352 *pcbEncoded = blob->cbData;
355 return ret;
358 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
359 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
360 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
362 BOOL ret;
363 /* This has two filetimes in a row, a NotBefore and a NotAfter */
364 const FILETIME *timePtr = pvStructInfo;
365 struct AsnEncodeSequenceItem items[] = {
366 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
367 { timePtr + 1, CRYPT_AsnEncodeChoiceOfTime, 0 },
370 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
371 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
372 pcbEncoded);
373 return ret;
376 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
377 * if they are empty.
379 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
380 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
381 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
382 DWORD *pcbEncoded)
384 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
385 static const BYTE asn1Null[] = { ASN_NULL, 0 };
386 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
387 (LPBYTE)asn1Null };
388 BOOL ret;
389 struct AsnEncodeSequenceItem items[2] = {
390 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
391 { NULL, CRYPT_CopyEncodedBlob, 0 },
394 if (algo->Parameters.cbData)
395 items[1].pvStructInfo = &algo->Parameters;
396 else
397 items[1].pvStructInfo = &nullBlob;
398 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
399 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
400 pcbEncoded);
401 return ret;
404 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType,
405 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
406 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
408 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
409 BOOL ret;
410 struct AsnEncodeSequenceItem items[] = {
411 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
412 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
415 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
416 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
417 pcbEncoded);
418 return ret;
421 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
422 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
423 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
425 BOOL ret;
427 __TRY
429 const CERT_PUBLIC_KEY_INFO *info = pvStructInfo;
430 struct AsnEncodeSequenceItem items[] = {
431 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
432 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
435 TRACE("Encoding public key with OID %s\n",
436 debugstr_a(info->Algorithm.pszObjId));
437 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
438 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
439 pcbEncoded);
441 __EXCEPT_PAGE_FAULT
443 SetLastError(STATUS_ACCESS_VIOLATION);
444 ret = FALSE;
446 __ENDTRY
447 return ret;
450 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
451 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
452 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
454 BOOL ret;
456 __TRY
458 const CERT_SIGNED_CONTENT_INFO *info = pvStructInfo;
459 struct AsnEncodeSequenceItem items[] = {
460 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
461 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
462 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
465 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
466 items[2].encodeFunc = CRYPT_AsnEncodeBits;
467 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
468 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
469 pcbEncoded);
471 __EXCEPT_PAGE_FAULT
473 SetLastError(STATUS_ACCESS_VIOLATION);
474 ret = FALSE;
476 __ENDTRY
477 return ret;
480 BOOL WINAPI CRYPT_AsnEncodePubKeyInfoNoNull(DWORD dwCertEncodingType,
481 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
482 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
484 BOOL ret;
485 const CERT_PUBLIC_KEY_INFO *info = pvStructInfo;
486 struct AsnEncodeSequenceItem items[] = {
487 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
488 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
491 TRACE("Encoding public key with OID %s\n",
492 debugstr_a(info->Algorithm.pszObjId));
493 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
494 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
495 pcbEncoded);
496 return ret;
499 /* Like in Windows, this blithely ignores the validity of the passed-in
500 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
501 * decode properly, see CRYPT_AsnDecodeCertInfo.
503 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
504 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
505 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
507 BOOL ret;
509 __TRY
511 const CERT_INFO *info = pvStructInfo;
512 struct AsnEncodeSequenceItem items[10] = {
513 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
514 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
515 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
516 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
517 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
518 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
519 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfoNoNull, 0 },
520 { 0 }
522 struct AsnConstructedItem constructed = { 0 };
523 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
524 DWORD cItem = 7, cSwapped = 0;
526 if (info->IssuerUniqueId.cbData)
528 swapped[cSwapped].tag = ASN_CONTEXT | 1;
529 swapped[cSwapped].pvStructInfo = &info->IssuerUniqueId;
530 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
531 items[cItem].pvStructInfo = &swapped[cSwapped];
532 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
533 cSwapped++;
534 cItem++;
536 if (info->SubjectUniqueId.cbData)
538 swapped[cSwapped].tag = ASN_CONTEXT | 2;
539 swapped[cSwapped].pvStructInfo = &info->SubjectUniqueId;
540 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
541 items[cItem].pvStructInfo = &swapped[cSwapped];
542 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
543 cSwapped++;
544 cItem++;
546 if (info->cExtension)
548 constructed.tag = 3;
549 constructed.pvStructInfo = &info->cExtension;
550 constructed.encodeFunc = CRYPT_AsnEncodeExtensions;
551 items[cItem].pvStructInfo = &constructed;
552 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
553 cItem++;
556 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
557 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
559 __EXCEPT_PAGE_FAULT
561 SetLastError(STATUS_ACCESS_VIOLATION);
562 ret = FALSE;
564 __ENDTRY
565 return ret;
568 static BOOL CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
569 BYTE *pbEncoded, DWORD *pcbEncoded)
571 struct AsnEncodeSequenceItem items[3] = {
572 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
573 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
574 { 0 }
576 DWORD cItem = 2;
577 BOOL ret;
579 TRACE("%p, %p, %ld\n", entry, pbEncoded, pbEncoded ? *pcbEncoded : 0);
581 if (entry->cExtension)
583 items[cItem].pvStructInfo = &entry->cExtension;
584 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
585 cItem++;
588 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
589 pbEncoded, pcbEncoded);
591 TRACE("returning %d (%08lx)\n", ret, GetLastError());
592 return ret;
595 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
596 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
597 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
599 DWORD bytesNeeded, dataLen, lenBytes, i;
600 const CRL_INFO *info = pvStructInfo;
601 const CRL_ENTRY *rgCRLEntry = info->rgCRLEntry;
602 BOOL ret = TRUE;
604 for (i = 0, dataLen = 0; ret && i < info->cCRLEntry; i++)
606 DWORD size;
608 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
609 if (ret)
610 dataLen += size;
612 if (ret)
614 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
615 bytesNeeded = 1 + lenBytes + dataLen;
616 if (!pbEncoded)
617 *pcbEncoded = bytesNeeded;
618 else
620 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
621 pcbEncoded, bytesNeeded)))
623 BYTE *out;
625 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
626 pbEncoded = *(BYTE **)pbEncoded;
627 out = pbEncoded;
628 *out++ = ASN_SEQUENCEOF;
629 CRYPT_EncodeLen(dataLen, out, &lenBytes);
630 out += lenBytes;
631 for (i = 0; i < info->cCRLEntry; i++)
633 DWORD size = dataLen;
635 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], out, &size);
636 out += size;
637 dataLen -= size;
639 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
640 CRYPT_FreeSpace(pEncodePara, pbEncoded);
644 return ret;
647 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
648 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
649 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
651 const DWORD *ver = pvStructInfo;
652 BOOL ret;
654 /* CRL_V1 is not encoded */
655 if (*ver == CRL_V1)
657 *pcbEncoded = 0;
658 ret = TRUE;
660 else
661 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
662 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
663 return ret;
666 /* Like in Windows, this blithely ignores the validity of the passed-in
667 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
668 * decode properly, see CRYPT_AsnDecodeCRLInfo.
670 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
671 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
672 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
674 BOOL ret;
676 __TRY
678 const CRL_INFO *info = pvStructInfo;
679 struct AsnEncodeSequenceItem items[7] = {
680 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
681 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
682 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
683 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
684 { 0 }
686 struct AsnConstructedItem constructed[1] = { { 0 } };
687 DWORD cItem = 4, cConstructed = 0;
689 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
691 items[cItem].pvStructInfo = &info->NextUpdate;
692 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
693 cItem++;
695 if (info->cCRLEntry)
697 items[cItem].pvStructInfo = info;
698 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
699 cItem++;
701 if (info->cExtension)
703 constructed[cConstructed].tag = 0;
704 constructed[cConstructed].pvStructInfo = &info->cExtension;
705 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
706 items[cItem].pvStructInfo = &constructed[cConstructed];
707 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
708 cConstructed++;
709 cItem++;
712 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
713 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
715 __EXCEPT_PAGE_FAULT
717 SetLastError(STATUS_ACCESS_VIOLATION);
718 ret = FALSE;
720 __ENDTRY
721 return ret;
724 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
725 DWORD *pcbEncoded)
727 BOOL ret;
728 struct AsnEncodeSequenceItem items[3] = {
729 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
730 { NULL, NULL, 0 },
731 { NULL, NULL, 0 },
733 DWORD cItem = 1;
735 TRACE("%p, %p, %ld\n", ext, pbEncoded, pbEncoded ? *pcbEncoded : 0);
737 if (ext->fCritical)
739 items[cItem].pvStructInfo = &ext->fCritical;
740 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
741 cItem++;
743 items[cItem].pvStructInfo = &ext->Value;
744 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
745 cItem++;
747 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
748 pbEncoded, pcbEncoded);
749 TRACE("returning %d (%08lx)\n", ret, GetLastError());
750 return ret;
753 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
754 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
755 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
757 BOOL ret;
759 __TRY
761 DWORD bytesNeeded, dataLen, lenBytes, i;
762 const CERT_EXTENSIONS *exts = pvStructInfo;
764 ret = TRUE;
765 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
767 DWORD size;
769 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
770 if (ret)
771 dataLen += size;
773 if (ret)
775 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
776 bytesNeeded = 1 + lenBytes + dataLen;
777 if (!pbEncoded)
778 *pcbEncoded = bytesNeeded;
779 else
781 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
782 pbEncoded, pcbEncoded, bytesNeeded)))
784 BYTE *out;
786 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
787 pbEncoded = *(BYTE **)pbEncoded;
788 out = pbEncoded;
789 *out++ = ASN_SEQUENCEOF;
790 CRYPT_EncodeLen(dataLen, out, &lenBytes);
791 out += lenBytes;
792 for (i = 0; i < exts->cExtension; i++)
794 DWORD size = dataLen;
796 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
797 out, &size);
798 out += size;
799 dataLen -= size;
801 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
802 CRYPT_FreeSpace(pEncodePara, pbEncoded);
807 __EXCEPT_PAGE_FAULT
809 SetLastError(STATUS_ACCESS_VIOLATION);
810 ret = FALSE;
812 __ENDTRY
813 return ret;
816 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
817 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
818 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
820 LPCSTR pszObjId = pvStructInfo;
821 DWORD bytesNeeded = 0, lenBytes;
822 BOOL ret = TRUE;
823 int firstPos = 0;
824 BYTE firstByte = 0;
826 TRACE("%s\n", debugstr_a(pszObjId));
828 if (pszObjId)
830 const char *ptr;
831 int val1, val2;
833 if (sscanf(pszObjId, "%d.%d%n", &val1, &val2, &firstPos) != 2)
835 SetLastError(CRYPT_E_ASN1_ERROR);
836 return FALSE;
838 bytesNeeded++;
839 firstByte = val1 * 40 + val2;
840 ptr = pszObjId + firstPos;
841 if (*ptr == '.')
843 ptr++;
844 firstPos++;
846 while (ret && *ptr)
848 int pos;
850 /* note I assume each component is at most 32-bits long in base 2 */
851 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
853 if (val1 >= 0x10000000)
854 bytesNeeded += 5;
855 else if (val1 >= 0x200000)
856 bytesNeeded += 4;
857 else if (val1 >= 0x4000)
858 bytesNeeded += 3;
859 else if (val1 >= 0x80)
860 bytesNeeded += 2;
861 else
862 bytesNeeded += 1;
863 ptr += pos;
864 if (*ptr == '.')
865 ptr++;
867 else
869 SetLastError(CRYPT_E_ASN1_ERROR);
870 return FALSE;
873 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
875 else
876 lenBytes = 1;
877 bytesNeeded += 1 + lenBytes;
878 if (pbEncoded)
880 if (*pcbEncoded < bytesNeeded)
882 SetLastError(ERROR_MORE_DATA);
883 ret = FALSE;
885 else
887 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
888 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
889 pbEncoded += lenBytes;
890 if (pszObjId)
892 const char *ptr;
893 int val, pos;
895 *pbEncoded++ = firstByte;
896 ptr = pszObjId + firstPos;
897 while (ret && *ptr)
899 sscanf(ptr, "%d%n", &val, &pos);
901 unsigned char outBytes[5];
902 int numBytes, i;
904 if (val >= 0x10000000)
905 numBytes = 5;
906 else if (val >= 0x200000)
907 numBytes = 4;
908 else if (val >= 0x4000)
909 numBytes = 3;
910 else if (val >= 0x80)
911 numBytes = 2;
912 else
913 numBytes = 1;
914 for (i = numBytes; i > 0; i--)
916 outBytes[i - 1] = val & 0x7f;
917 val >>= 7;
919 for (i = 0; i < numBytes - 1; i++)
920 *pbEncoded++ = outBytes[i] | 0x80;
921 *pbEncoded++ = outBytes[i];
922 ptr += pos;
923 if (*ptr == '.')
924 ptr++;
930 *pcbEncoded = bytesNeeded;
931 return ret;
934 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
935 BYTE tag, DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
936 DWORD *pcbEncoded)
938 BOOL ret = TRUE;
939 LPCSTR str = (LPCSTR)value->Value.pbData;
940 DWORD bytesNeeded, lenBytes, encodedLen;
942 encodedLen = value->Value.cbData ? value->Value.cbData : strlen(str);
943 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
944 bytesNeeded = 1 + lenBytes + encodedLen;
945 if (!pbEncoded)
946 *pcbEncoded = bytesNeeded;
947 else
949 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
950 pbEncoded, pcbEncoded, bytesNeeded)))
952 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
953 pbEncoded = *(BYTE **)pbEncoded;
954 *pbEncoded++ = tag;
955 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
956 pbEncoded += lenBytes;
957 memcpy(pbEncoded, str, encodedLen);
960 return ret;
963 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
964 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
965 DWORD *pcbEncoded)
967 BOOL ret = TRUE;
968 LPCWSTR str = (LPCWSTR)value->Value.pbData;
969 DWORD bytesNeeded, lenBytes, strLen;
971 if (value->Value.cbData)
972 strLen = value->Value.cbData / sizeof(WCHAR);
973 else if (value->Value.pbData)
974 strLen = lstrlenW(str);
975 else
976 strLen = 0;
977 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
978 bytesNeeded = 1 + lenBytes + strLen * 2;
979 if (!pbEncoded)
980 *pcbEncoded = bytesNeeded;
981 else
983 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
984 pbEncoded, pcbEncoded, bytesNeeded)))
986 DWORD i;
988 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
989 pbEncoded = *(BYTE **)pbEncoded;
990 *pbEncoded++ = ASN_BMPSTRING;
991 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
992 pbEncoded += lenBytes;
993 for (i = 0; i < strLen; i++)
995 *pbEncoded++ = (str[i] & 0xff00) >> 8;
996 *pbEncoded++ = str[i] & 0x00ff;
1000 return ret;
1003 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
1004 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
1005 DWORD *pcbEncoded)
1007 BOOL ret = TRUE;
1008 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1009 DWORD bytesNeeded, lenBytes, encodedLen, strLen;
1011 if (value->Value.cbData)
1012 strLen = value->Value.cbData / sizeof(WCHAR);
1013 else if (str)
1014 strLen = lstrlenW(str);
1015 else
1016 strLen = 0;
1017 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
1018 NULL);
1019 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1020 bytesNeeded = 1 + lenBytes + encodedLen;
1021 if (!pbEncoded)
1022 *pcbEncoded = bytesNeeded;
1023 else
1025 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1026 pbEncoded, pcbEncoded, bytesNeeded)))
1028 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1029 pbEncoded = *(BYTE **)pbEncoded;
1030 *pbEncoded++ = ASN_UTF8STRING;
1031 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1032 pbEncoded += lenBytes;
1033 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
1034 bytesNeeded - lenBytes - 1, NULL, NULL);
1037 return ret;
1040 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
1041 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1042 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1044 BOOL ret = TRUE;
1046 __TRY
1048 const CERT_NAME_VALUE *value = pvStructInfo;
1050 switch (value->dwValueType)
1052 case CERT_RDN_ANY_TYPE:
1053 /* explicitly disallowed */
1054 SetLastError(E_INVALIDARG);
1055 ret = FALSE;
1056 break;
1057 case CERT_RDN_ENCODED_BLOB:
1058 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
1059 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1060 break;
1061 case CERT_RDN_OCTET_STRING:
1062 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1063 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1064 break;
1065 case CERT_RDN_NUMERIC_STRING:
1066 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1067 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1068 break;
1069 case CERT_RDN_PRINTABLE_STRING:
1070 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1071 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1072 break;
1073 case CERT_RDN_TELETEX_STRING:
1074 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1075 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1076 break;
1077 case CERT_RDN_VIDEOTEX_STRING:
1078 ret = CRYPT_AsnEncodeStringCoerce(value,
1079 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1080 break;
1081 case CERT_RDN_IA5_STRING:
1082 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1083 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1084 break;
1085 case CERT_RDN_GRAPHIC_STRING:
1086 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1087 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1088 break;
1089 case CERT_RDN_VISIBLE_STRING:
1090 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1091 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1092 break;
1093 case CERT_RDN_GENERAL_STRING:
1094 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1095 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1096 break;
1097 case CERT_RDN_UNIVERSAL_STRING:
1098 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1099 SetLastError(CRYPT_E_ASN1_CHOICE);
1100 ret = FALSE;
1101 break;
1102 case CERT_RDN_BMP_STRING:
1103 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1104 pbEncoded, pcbEncoded);
1105 break;
1106 case CERT_RDN_UTF8_STRING:
1107 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1108 pbEncoded, pcbEncoded);
1109 break;
1110 default:
1111 SetLastError(CRYPT_E_ASN1_CHOICE);
1112 ret = FALSE;
1115 __EXCEPT_PAGE_FAULT
1117 SetLastError(STATUS_ACCESS_VIOLATION);
1118 ret = FALSE;
1120 __ENDTRY
1121 return ret;
1124 static BOOL CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1125 const CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1126 BYTE *pbEncoded, DWORD *pcbEncoded)
1128 DWORD bytesNeeded = 0, lenBytes, size;
1129 BOOL ret;
1131 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1132 0, NULL, NULL, &size);
1133 if (ret)
1135 bytesNeeded += size;
1136 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1137 * with dwValueType, so "cast" it to get its encoded size
1139 ret = nameValueEncodeFunc(dwCertEncodingType, NULL, &attr->dwValueType,
1140 0, NULL, NULL, &size);
1141 if (ret)
1143 bytesNeeded += size;
1144 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1145 bytesNeeded += 1 + lenBytes;
1146 if (pbEncoded)
1148 if (*pcbEncoded < bytesNeeded)
1150 SetLastError(ERROR_MORE_DATA);
1151 ret = FALSE;
1153 else
1155 *pbEncoded++ = ASN_SEQUENCE;
1156 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1157 &lenBytes);
1158 pbEncoded += lenBytes;
1159 size = bytesNeeded - 1 - lenBytes;
1160 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1161 attr->pszObjId, 0, NULL, pbEncoded, &size);
1162 if (ret)
1164 pbEncoded += size;
1165 size = bytesNeeded - 1 - lenBytes - size;
1166 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1167 &attr->dwValueType, 0, NULL, pbEncoded, &size);
1168 if (!ret)
1169 *pcbEncoded = size;
1173 if (ret)
1174 *pcbEncoded = bytesNeeded;
1176 else
1178 /* Have to propagate index of failing character */
1179 *pcbEncoded = size;
1182 return ret;
1185 static int __cdecl BLOBComp(const void *l, const void *r)
1187 const CRYPT_DER_BLOB *a = l, *b = r;
1188 int ret;
1190 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1191 ret = a->cbData - b->cbData;
1192 return ret;
1195 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1197 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1198 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1199 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1201 const CRYPT_BLOB_ARRAY *set = pvStructInfo;
1202 DWORD bytesNeeded = 0, lenBytes, i;
1203 BOOL ret;
1205 for (i = 0; i < set->cBlob; i++)
1206 bytesNeeded += set->rgBlob[i].cbData;
1207 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1208 bytesNeeded += 1 + lenBytes;
1209 if (!pbEncoded)
1211 *pcbEncoded = bytesNeeded;
1212 ret = TRUE;
1214 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1215 pbEncoded, pcbEncoded, bytesNeeded)))
1217 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1218 pbEncoded = *(BYTE **)pbEncoded;
1219 qsort(set->rgBlob, set->cBlob, sizeof(CRYPT_DER_BLOB), BLOBComp);
1220 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1221 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1222 pbEncoded += lenBytes;
1223 for (i = 0; i < set->cBlob; i++)
1225 memcpy(pbEncoded, set->rgBlob[i].pbData, set->rgBlob[i].cbData);
1226 pbEncoded += set->rgBlob[i].cbData;
1229 return ret;
1232 struct DERSetDescriptor
1234 DWORD cItems;
1235 const void *items;
1236 size_t itemSize;
1237 size_t itemOffset;
1238 CryptEncodeObjectExFunc encode;
1241 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,
1242 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1243 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1245 const struct DERSetDescriptor *desc = pvStructInfo;
1246 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1247 BOOL ret = TRUE;
1248 DWORD i;
1250 if (desc->cItems)
1252 setOf.rgBlob = CryptMemAlloc(desc->cItems * sizeof(CRYPT_DER_BLOB));
1253 if (!setOf.rgBlob)
1254 ret = FALSE;
1255 else
1257 setOf.cBlob = desc->cItems;
1258 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1261 for (i = 0; ret && i < setOf.cBlob; i++)
1263 ret = desc->encode(dwCertEncodingType, lpszStructType,
1264 (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
1265 0, NULL, NULL, &setOf.rgBlob[i].cbData);
1266 if (ret)
1268 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1269 if (!setOf.rgBlob[i].pbData)
1270 ret = FALSE;
1271 else
1272 ret = desc->encode(dwCertEncodingType, lpszStructType,
1273 (const BYTE *)desc->items + i * desc->itemSize +
1274 desc->itemOffset, 0, NULL, setOf.rgBlob[i].pbData,
1275 &setOf.rgBlob[i].cbData);
1277 /* Some functions propagate their errors through the size */
1278 if (!ret)
1279 *pcbEncoded = setOf.rgBlob[i].cbData;
1281 if (ret)
1283 DWORD bytesNeeded = 0, lenBytes;
1285 for (i = 0; i < setOf.cBlob; i++)
1286 bytesNeeded += setOf.rgBlob[i].cbData;
1287 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1288 bytesNeeded += 1 + lenBytes;
1289 if (!pbEncoded)
1290 *pcbEncoded = bytesNeeded;
1291 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1292 pbEncoded, pcbEncoded, bytesNeeded)))
1294 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1295 pbEncoded = *(BYTE **)pbEncoded;
1296 qsort(setOf.rgBlob, setOf.cBlob, sizeof(CRYPT_DER_BLOB),
1297 BLOBComp);
1298 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1299 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1300 pbEncoded += lenBytes;
1301 for (i = 0; i < setOf.cBlob; i++)
1303 memcpy(pbEncoded, setOf.rgBlob[i].pbData,
1304 setOf.rgBlob[i].cbData);
1305 pbEncoded += setOf.rgBlob[i].cbData;
1309 for (i = 0; i < setOf.cBlob; i++)
1310 CryptMemFree(setOf.rgBlob[i].pbData);
1311 CryptMemFree(setOf.rgBlob);
1312 return ret;
1315 static BOOL CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, const CERT_RDN *rdn,
1316 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1317 DWORD *pcbEncoded)
1319 BOOL ret;
1320 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1322 __TRY
1324 DWORD i;
1326 ret = TRUE;
1327 if (rdn->cRDNAttr)
1329 setOf.rgBlob = CryptMemAlloc(rdn->cRDNAttr *
1330 sizeof(CRYPT_DER_BLOB));
1331 if (!setOf.rgBlob)
1332 ret = FALSE;
1333 else
1335 setOf.cBlob = rdn->cRDNAttr;
1336 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1339 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1341 setOf.rgBlob[i].cbData = 0;
1342 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1343 nameValueEncodeFunc, NULL, &setOf.rgBlob[i].cbData);
1344 if (ret)
1346 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1347 if (!setOf.rgBlob[i].pbData)
1348 ret = FALSE;
1349 else
1350 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1351 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1352 setOf.rgBlob[i].pbData, &setOf.rgBlob[i].cbData);
1354 if (!ret)
1356 /* Have to propagate index of failing character */
1357 *pcbEncoded = setOf.rgBlob[i].cbData;
1360 if (ret)
1361 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1362 pbEncoded, pcbEncoded);
1363 for (i = 0; i < setOf.cBlob; i++)
1364 CryptMemFree(setOf.rgBlob[i].pbData);
1366 __EXCEPT_PAGE_FAULT
1368 SetLastError(STATUS_ACCESS_VIOLATION);
1369 ret = FALSE;
1371 __ENDTRY
1372 CryptMemFree(setOf.rgBlob);
1373 return ret;
1376 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1377 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1378 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1380 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1381 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1382 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1383 DWORD *pcbEncoded)
1385 const CERT_NAME_VALUE *value = pvStructInfo;
1386 BOOL ret;
1388 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1389 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1390 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1391 else
1392 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1393 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1394 return ret;
1397 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1398 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1399 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1401 BOOL ret = TRUE;
1403 __TRY
1405 const CERT_NAME_INFO *info = pvStructInfo;
1406 DWORD bytesNeeded = 0, lenBytes, size, i;
1408 TRACE("encoding name with %ld RDNs\n", info->cRDN);
1409 ret = TRUE;
1410 for (i = 0; ret && i < info->cRDN; i++)
1412 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1413 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1414 if (ret)
1415 bytesNeeded += size;
1416 else
1417 *pcbEncoded = size;
1419 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1420 bytesNeeded += 1 + lenBytes;
1421 if (ret)
1423 if (!pbEncoded)
1424 *pcbEncoded = bytesNeeded;
1425 else
1427 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1428 pbEncoded, pcbEncoded, bytesNeeded)))
1430 BYTE *out;
1432 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1433 pbEncoded = *(BYTE **)pbEncoded;
1434 out = pbEncoded;
1435 *out++ = ASN_SEQUENCEOF;
1436 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
1437 out += lenBytes;
1438 for (i = 0; ret && i < info->cRDN; i++)
1440 size = bytesNeeded;
1441 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1442 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1443 out, &size);
1444 if (ret)
1446 out += size;
1447 bytesNeeded -= size;
1449 else
1450 *pcbEncoded = size;
1452 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1453 CRYPT_FreeSpace(pEncodePara, pbEncoded);
1458 __EXCEPT_PAGE_FAULT
1460 SetLastError(STATUS_ACCESS_VIOLATION);
1461 ret = FALSE;
1463 __ENDTRY
1464 return ret;
1467 static BOOL WINAPI CRYPT_AsnEncodeCTLVersion(DWORD dwCertEncodingType,
1468 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1469 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1471 const DWORD *ver = pvStructInfo;
1472 BOOL ret;
1474 /* CTL_V1 is not encoded */
1475 if (*ver == CTL_V1)
1477 *pcbEncoded = 0;
1478 ret = TRUE;
1480 else
1481 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
1482 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1483 return ret;
1486 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
1487 * if they are empty and the OID is not empty (otherwise omits them.)
1489 static BOOL WINAPI CRYPT_AsnEncodeCTLSubjectAlgorithm(
1490 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1491 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1492 DWORD *pcbEncoded)
1494 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
1495 BOOL ret;
1496 struct AsnEncodeSequenceItem items[2] = {
1497 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
1499 DWORD cItem = 1;
1501 if (algo->pszObjId)
1503 static const BYTE asn1Null[] = { ASN_NULL, 0 };
1504 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
1505 (LPBYTE)asn1Null };
1507 if (algo->Parameters.cbData)
1508 items[cItem].pvStructInfo = &algo->Parameters;
1509 else
1510 items[cItem].pvStructInfo = &nullBlob;
1511 items[cItem].encodeFunc = CRYPT_CopyEncodedBlob;
1512 cItem++;
1514 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1515 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1516 return ret;
1519 static BOOL CRYPT_AsnEncodeCTLEntry(const CTL_ENTRY *entry,
1520 BYTE *pbEncoded, DWORD *pcbEncoded)
1522 struct AsnEncodeSequenceItem items[2] = {
1523 { &entry->SubjectIdentifier, CRYPT_AsnEncodeOctets, 0 },
1524 { &entry->cAttribute, CRYPT_AsnEncodePKCSAttributes, 0 },
1526 BOOL ret;
1528 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1529 ARRAY_SIZE(items), 0, NULL, pbEncoded, pcbEncoded);
1530 return ret;
1533 struct CTLEntries
1535 DWORD cEntry;
1536 CTL_ENTRY *rgEntry;
1539 static BOOL WINAPI CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType,
1540 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1541 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1543 BOOL ret;
1544 DWORD bytesNeeded, dataLen, lenBytes, i;
1545 const struct CTLEntries *entries = pvStructInfo;
1547 ret = TRUE;
1548 for (i = 0, dataLen = 0; ret && i < entries->cEntry; i++)
1550 DWORD size;
1552 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i], NULL, &size);
1553 if (ret)
1554 dataLen += size;
1556 if (ret)
1558 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1559 bytesNeeded = 1 + lenBytes + dataLen;
1560 if (!pbEncoded)
1561 *pcbEncoded = bytesNeeded;
1562 else
1564 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1565 pbEncoded, pcbEncoded, bytesNeeded)))
1567 BYTE *out;
1569 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1570 pbEncoded = *(BYTE **)pbEncoded;
1571 out = pbEncoded;
1572 *out++ = ASN_SEQUENCEOF;
1573 CRYPT_EncodeLen(dataLen, out, &lenBytes);
1574 out += lenBytes;
1575 for (i = 0; ret && i < entries->cEntry; i++)
1577 DWORD size = dataLen;
1579 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i],
1580 out, &size);
1581 out += size;
1582 dataLen -= size;
1584 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1585 CRYPT_FreeSpace(pEncodePara, pbEncoded);
1589 return ret;
1592 static BOOL WINAPI CRYPT_AsnEncodeCTL(DWORD dwCertEncodingType,
1593 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1594 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1596 BOOL ret = FALSE;
1598 __TRY
1600 const CTL_INFO *info = pvStructInfo;
1601 struct AsnEncodeSequenceItem items[9] = {
1602 { &info->dwVersion, CRYPT_AsnEncodeCTLVersion, 0 },
1603 { &info->SubjectUsage, CRYPT_AsnEncodeEnhancedKeyUsage, 0 },
1605 struct AsnConstructedItem constructed = { 0 };
1606 DWORD cItem = 2;
1608 if (info->ListIdentifier.cbData)
1610 items[cItem].pvStructInfo = &info->ListIdentifier;
1611 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
1612 cItem++;
1614 if (info->SequenceNumber.cbData)
1616 items[cItem].pvStructInfo = &info->SequenceNumber;
1617 items[cItem].encodeFunc = CRYPT_AsnEncodeInteger;
1618 cItem++;
1620 items[cItem].pvStructInfo = &info->ThisUpdate;
1621 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1622 cItem++;
1623 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
1625 items[cItem].pvStructInfo = &info->NextUpdate;
1626 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1627 cItem++;
1629 items[cItem].pvStructInfo = &info->SubjectAlgorithm;
1630 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLSubjectAlgorithm;
1631 cItem++;
1632 if (info->cCTLEntry)
1634 items[cItem].pvStructInfo = &info->cCTLEntry;
1635 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLEntries;
1636 cItem++;
1638 if (info->cExtension)
1640 constructed.tag = 0;
1641 constructed.pvStructInfo = &info->cExtension;
1642 constructed.encodeFunc = CRYPT_AsnEncodeExtensions;
1643 items[cItem].pvStructInfo = &constructed;
1644 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1645 cItem++;
1647 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1648 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1650 __EXCEPT_PAGE_FAULT
1652 SetLastError(STATUS_ACCESS_VIOLATION);
1654 __ENDTRY
1655 return ret;
1658 static BOOL CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType,
1659 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1660 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1662 BOOL ret = FALSE;
1664 __TRY
1666 const CRYPT_SMIME_CAPABILITY *capability = pvStructInfo;
1668 if (!capability->pszObjId)
1669 SetLastError(E_INVALIDARG);
1670 else
1672 struct AsnEncodeSequenceItem items[] = {
1673 { capability->pszObjId, CRYPT_AsnEncodeOid, 0 },
1674 { &capability->Parameters, CRYPT_CopyEncodedBlob, 0 },
1677 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1678 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
1679 pcbEncoded);
1682 __EXCEPT_PAGE_FAULT
1684 SetLastError(STATUS_ACCESS_VIOLATION);
1686 __ENDTRY
1687 return ret;
1690 static BOOL WINAPI CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType,
1691 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1692 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1694 BOOL ret = FALSE;
1696 __TRY
1698 DWORD bytesNeeded, dataLen, lenBytes, i;
1699 const CRYPT_SMIME_CAPABILITIES *capabilities = pvStructInfo;
1701 ret = TRUE;
1702 for (i = 0, dataLen = 0; ret && i < capabilities->cCapability; i++)
1704 DWORD size;
1706 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType, NULL,
1707 &capabilities->rgCapability[i], 0, NULL, NULL, &size);
1708 if (ret)
1709 dataLen += size;
1711 if (ret)
1713 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1714 bytesNeeded = 1 + lenBytes + dataLen;
1715 if (!pbEncoded)
1716 *pcbEncoded = bytesNeeded;
1717 else
1719 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1720 pbEncoded, pcbEncoded, bytesNeeded)))
1722 BYTE *out;
1724 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1725 pbEncoded = *(BYTE **)pbEncoded;
1726 out = pbEncoded;
1727 *out++ = ASN_SEQUENCEOF;
1728 CRYPT_EncodeLen(dataLen, out, &lenBytes);
1729 out += lenBytes;
1730 for (i = 0; i < capabilities->cCapability; i++)
1732 DWORD size = dataLen;
1734 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType,
1735 NULL, &capabilities->rgCapability[i], 0, NULL,
1736 out, &size);
1737 out += size;
1738 dataLen -= size;
1740 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1741 CRYPT_FreeSpace(pEncodePara, pbEncoded);
1746 __EXCEPT_PAGE_FAULT
1748 SetLastError(STATUS_ACCESS_VIOLATION);
1750 __ENDTRY
1751 return ret;
1754 static BOOL WINAPI CRYPT_AsnEncodeNoticeNumbers(DWORD dwCertEncodingType,
1755 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1756 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1758 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
1759 DWORD bytesNeeded, dataLen, lenBytes, i;
1760 BOOL ret = TRUE;
1762 for (i = 0, dataLen = 0; ret && i < noticeRef->cNoticeNumbers; i++)
1764 DWORD size;
1766 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
1767 &noticeRef->rgNoticeNumbers[i], 0, NULL, NULL, &size);
1768 if (ret)
1769 dataLen += size;
1771 if (ret)
1773 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1774 bytesNeeded = 1 + lenBytes + dataLen;
1775 if (!pbEncoded)
1776 *pcbEncoded = bytesNeeded;
1777 else
1779 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1780 pcbEncoded, bytesNeeded)))
1782 BYTE *out;
1784 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1785 pbEncoded = *(BYTE **)pbEncoded;
1786 out = pbEncoded;
1787 *out++ = ASN_SEQUENCE;
1788 CRYPT_EncodeLen(dataLen, out, &lenBytes);
1789 out += lenBytes;
1790 for (i = 0; i < noticeRef->cNoticeNumbers; i++)
1792 DWORD size = dataLen;
1794 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
1795 &noticeRef->rgNoticeNumbers[i], 0, NULL, out, &size);
1796 out += size;
1797 dataLen -= size;
1799 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1800 CRYPT_FreeSpace(pEncodePara, pbEncoded);
1804 return ret;
1807 static BOOL WINAPI CRYPT_AsnEncodeNoticeReference(DWORD dwCertEncodingType,
1808 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1809 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1811 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
1812 BOOL ret;
1813 CERT_NAME_VALUE orgValue = { CERT_RDN_IA5_STRING,
1814 { 0, (LPBYTE)noticeRef->pszOrganization } };
1815 struct AsnEncodeSequenceItem items[] = {
1816 { &orgValue, CRYPT_AsnEncodeNameValue, 0 },
1817 { noticeRef, CRYPT_AsnEncodeNoticeNumbers, 0 },
1820 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1821 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
1822 pcbEncoded);
1823 return ret;
1826 static BOOL WINAPI CRYPT_AsnEncodePolicyQualifierUserNotice(
1827 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1828 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1829 DWORD *pcbEncoded)
1831 BOOL ret = FALSE;
1833 __TRY
1835 const CERT_POLICY_QUALIFIER_USER_NOTICE *notice = pvStructInfo;
1836 struct AsnEncodeSequenceItem items[2];
1837 CERT_NAME_VALUE displayTextValue;
1838 DWORD cItem = 0;
1840 if (notice->pNoticeReference)
1842 items[cItem].encodeFunc = CRYPT_AsnEncodeNoticeReference;
1843 items[cItem].pvStructInfo = notice->pNoticeReference;
1844 cItem++;
1846 if (notice->pszDisplayText)
1848 displayTextValue.dwValueType = CERT_RDN_BMP_STRING;
1849 displayTextValue.Value.cbData = 0;
1850 displayTextValue.Value.pbData = (LPBYTE)notice->pszDisplayText;
1851 items[cItem].encodeFunc = CRYPT_AsnEncodeNameValue;
1852 items[cItem].pvStructInfo = &displayTextValue;
1853 cItem++;
1855 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1856 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1858 __EXCEPT_PAGE_FAULT
1860 SetLastError(STATUS_ACCESS_VIOLATION);
1862 __ENDTRY
1863 return ret;
1866 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1867 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1868 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1870 BOOL ret = FALSE;
1872 __TRY
1874 const CRYPT_ATTRIBUTE *attr = pvStructInfo;
1876 if (!attr->pszObjId)
1877 SetLastError(E_INVALIDARG);
1878 else
1880 struct AsnEncodeSequenceItem items[2] = {
1881 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1882 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1885 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1886 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
1887 pcbEncoded);
1890 __EXCEPT_PAGE_FAULT
1892 SetLastError(STATUS_ACCESS_VIOLATION);
1894 __ENDTRY
1895 return ret;
1898 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(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_ATTRIBUTES *attributes = pvStructInfo;
1907 struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
1908 sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
1910 ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
1911 &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1913 __EXCEPT_PAGE_FAULT
1915 SetLastError(STATUS_ACCESS_VIOLATION);
1917 __ENDTRY
1918 return ret;
1921 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1922 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
1923 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1924 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1925 DWORD *pcbEncoded)
1927 const CRYPT_CONTENT_INFO *info = pvStructInfo;
1928 struct AsnEncodeSequenceItem items[2] = {
1929 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1930 { NULL, NULL, 0 },
1932 struct AsnConstructedItem constructed = { 0 };
1933 DWORD cItem = 1;
1935 if (info->Content.cbData)
1937 constructed.tag = 0;
1938 constructed.pvStructInfo = &info->Content;
1939 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1940 items[cItem].pvStructInfo = &constructed;
1941 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1942 cItem++;
1944 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1945 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1948 BOOL CRYPT_AsnEncodePKCSDigestedData(const CRYPT_DIGESTED_DATA *digestedData,
1949 void *pvData, DWORD *pcbData)
1951 struct AsnEncodeSequenceItem items[] = {
1952 { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1953 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
1954 0 },
1955 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1956 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1959 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, ARRAY_SIZE(items), 0, NULL, pvData, pcbData);
1962 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1963 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1964 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1966 BOOL ret = FALSE;
1968 __TRY
1970 const CRYPT_CONTENT_INFO *info = pvStructInfo;
1972 if (!info->pszObjId)
1973 SetLastError(E_INVALIDARG);
1974 else
1975 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
1976 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1977 pcbEncoded);
1979 __EXCEPT_PAGE_FAULT
1981 SetLastError(STATUS_ACCESS_VIOLATION);
1983 __ENDTRY
1984 return ret;
1987 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1988 BYTE tag, DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
1989 DWORD *pcbEncoded)
1991 BOOL ret = TRUE;
1992 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1993 DWORD bytesNeeded, lenBytes, encodedLen;
1995 if (value->Value.cbData)
1996 encodedLen = value->Value.cbData / sizeof(WCHAR);
1997 else if (str)
1998 encodedLen = lstrlenW(str);
1999 else
2000 encodedLen = 0;
2001 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2002 bytesNeeded = 1 + lenBytes + encodedLen;
2003 if (!pbEncoded)
2004 *pcbEncoded = bytesNeeded;
2005 else
2007 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2008 pbEncoded, pcbEncoded, bytesNeeded)))
2010 DWORD i;
2012 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2013 pbEncoded = *(BYTE **)pbEncoded;
2014 *pbEncoded++ = tag;
2015 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
2016 pbEncoded += lenBytes;
2017 for (i = 0; i < encodedLen; i++)
2018 *pbEncoded++ = (BYTE)str[i];
2021 return ret;
2024 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
2025 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2026 DWORD *pcbEncoded)
2028 BOOL ret = TRUE;
2029 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2030 DWORD bytesNeeded, lenBytes, encodedLen;
2032 if (value->Value.cbData)
2033 encodedLen = value->Value.cbData / sizeof(WCHAR);
2034 else if (str)
2035 encodedLen = lstrlenW(str);
2036 else
2037 encodedLen = 0;
2038 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2039 bytesNeeded = 1 + lenBytes + encodedLen;
2040 if (!pbEncoded)
2041 *pcbEncoded = bytesNeeded;
2042 else
2044 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2045 pbEncoded, pcbEncoded, bytesNeeded)))
2047 DWORD i;
2048 BYTE *ptr;
2050 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2051 ptr = *(BYTE **)pbEncoded;
2052 else
2053 ptr = pbEncoded;
2054 *ptr++ = ASN_NUMERICSTRING;
2055 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2056 ptr += lenBytes;
2057 for (i = 0; ret && i < encodedLen; i++)
2059 if ('0' <= str[i] && str[i] <= '9')
2060 *ptr++ = (BYTE)str[i];
2061 else
2063 *pcbEncoded = i;
2064 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
2065 ret = FALSE;
2068 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2069 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2072 return ret;
2075 static inline BOOL isprintableW(WCHAR wc)
2077 return wc && wcschr( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '()+,-./:=?", wc );
2080 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
2081 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2082 DWORD *pcbEncoded)
2084 BOOL ret = TRUE;
2085 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2086 DWORD bytesNeeded, lenBytes, encodedLen;
2088 if (value->Value.cbData)
2089 encodedLen = value->Value.cbData / sizeof(WCHAR);
2090 else if (str)
2091 encodedLen = lstrlenW(str);
2092 else
2093 encodedLen = 0;
2094 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2095 bytesNeeded = 1 + lenBytes + encodedLen;
2096 if (!pbEncoded)
2097 *pcbEncoded = bytesNeeded;
2098 else
2100 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2101 pbEncoded, pcbEncoded, bytesNeeded)))
2103 DWORD i;
2104 BYTE *ptr;
2106 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2107 ptr = *(BYTE **)pbEncoded;
2108 else
2109 ptr = pbEncoded;
2110 *ptr++ = ASN_PRINTABLESTRING;
2111 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2112 ptr += lenBytes;
2113 for (i = 0; ret && i < encodedLen; i++)
2115 if (isprintableW(str[i]))
2116 *ptr++ = (BYTE)str[i];
2117 else
2119 *pcbEncoded = i;
2120 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
2121 ret = FALSE;
2124 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2125 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2128 return ret;
2131 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
2132 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2133 DWORD *pcbEncoded)
2135 BOOL ret = TRUE;
2136 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2137 DWORD bytesNeeded, lenBytes, encodedLen;
2139 if (value->Value.cbData)
2140 encodedLen = value->Value.cbData / sizeof(WCHAR);
2141 else if (str)
2142 encodedLen = lstrlenW(str);
2143 else
2144 encodedLen = 0;
2145 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2146 bytesNeeded = 1 + lenBytes + encodedLen;
2147 if (!pbEncoded)
2148 *pcbEncoded = bytesNeeded;
2149 else
2151 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2152 pbEncoded, pcbEncoded, bytesNeeded)))
2154 DWORD i;
2155 BYTE *ptr;
2157 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2158 ptr = *(BYTE **)pbEncoded;
2159 else
2160 ptr = pbEncoded;
2161 *ptr++ = ASN_IA5STRING;
2162 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2163 ptr += lenBytes;
2164 for (i = 0; ret && i < encodedLen; i++)
2166 if (str[i] <= 0x7f)
2167 *ptr++ = (BYTE)str[i];
2168 else
2170 *pcbEncoded = i;
2171 SetLastError(CRYPT_E_INVALID_IA5_STRING);
2172 ret = FALSE;
2175 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2176 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2179 return ret;
2182 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
2183 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2184 DWORD *pcbEncoded)
2186 BOOL ret = TRUE;
2187 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2188 DWORD bytesNeeded, lenBytes, strLen;
2190 /* FIXME: doesn't handle composite characters */
2191 if (value->Value.cbData)
2192 strLen = value->Value.cbData / sizeof(WCHAR);
2193 else if (str)
2194 strLen = lstrlenW(str);
2195 else
2196 strLen = 0;
2197 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
2198 bytesNeeded = 1 + lenBytes + strLen * 4;
2199 if (!pbEncoded)
2200 *pcbEncoded = bytesNeeded;
2201 else
2203 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2204 pbEncoded, pcbEncoded, bytesNeeded)))
2206 DWORD i;
2208 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2209 pbEncoded = *(BYTE **)pbEncoded;
2210 *pbEncoded++ = ASN_UNIVERSALSTRING;
2211 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
2212 pbEncoded += lenBytes;
2213 for (i = 0; i < strLen; i++)
2215 *pbEncoded++ = 0;
2216 *pbEncoded++ = 0;
2217 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
2218 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
2222 return ret;
2225 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
2226 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2227 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2229 BOOL ret = FALSE;
2231 __TRY
2233 const CERT_NAME_VALUE *value = pvStructInfo;
2235 switch (value->dwValueType)
2237 case CERT_RDN_ANY_TYPE:
2238 case CERT_RDN_ENCODED_BLOB:
2239 case CERT_RDN_OCTET_STRING:
2240 SetLastError(CRYPT_E_NOT_CHAR_STRING);
2241 break;
2242 case CERT_RDN_NUMERIC_STRING:
2243 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
2244 pbEncoded, pcbEncoded);
2245 break;
2246 case CERT_RDN_PRINTABLE_STRING:
2247 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
2248 pbEncoded, pcbEncoded);
2249 break;
2250 case CERT_RDN_TELETEX_STRING:
2251 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
2252 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2253 break;
2254 case CERT_RDN_VIDEOTEX_STRING:
2255 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
2256 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2257 break;
2258 case CERT_RDN_IA5_STRING:
2259 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
2260 pbEncoded, pcbEncoded);
2261 break;
2262 case CERT_RDN_GRAPHIC_STRING:
2263 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
2264 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2265 break;
2266 case CERT_RDN_VISIBLE_STRING:
2267 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
2268 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2269 break;
2270 case CERT_RDN_GENERAL_STRING:
2271 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
2272 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2273 break;
2274 case CERT_RDN_UNIVERSAL_STRING:
2275 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
2276 pbEncoded, pcbEncoded);
2277 break;
2278 case CERT_RDN_BMP_STRING:
2279 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
2280 pbEncoded, pcbEncoded);
2281 break;
2282 case CERT_RDN_UTF8_STRING:
2283 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
2284 pbEncoded, pcbEncoded);
2285 break;
2286 default:
2287 SetLastError(CRYPT_E_ASN1_CHOICE);
2290 __EXCEPT_PAGE_FAULT
2292 SetLastError(STATUS_ACCESS_VIOLATION);
2294 __ENDTRY
2295 return ret;
2298 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
2299 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2300 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2302 BOOL ret;
2304 __TRY
2306 const CERT_NAME_INFO *info = pvStructInfo;
2307 DWORD bytesNeeded = 0, lenBytes, size, i;
2309 TRACE("encoding name with %ld RDNs\n", info->cRDN);
2310 ret = TRUE;
2311 for (i = 0; ret && i < info->cRDN; i++)
2313 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
2314 CRYPT_AsnEncodeNameValue, NULL, &size);
2315 if (ret)
2316 bytesNeeded += size;
2318 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2319 bytesNeeded += 1 + lenBytes;
2320 if (ret)
2322 if (!pbEncoded)
2323 *pcbEncoded = bytesNeeded;
2324 else
2326 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2327 pbEncoded, pcbEncoded, bytesNeeded)))
2329 BYTE *out;
2331 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2332 pbEncoded = *(BYTE **)pbEncoded;
2333 out = pbEncoded;
2334 *out++ = ASN_SEQUENCEOF;
2335 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
2336 out += lenBytes;
2337 for (i = 0; ret && i < info->cRDN; i++)
2339 size = bytesNeeded;
2340 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
2341 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, out, &size);
2342 if (ret)
2344 out += size;
2345 bytesNeeded -= size;
2348 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2349 CRYPT_FreeSpace(pEncodePara, pbEncoded);
2354 __EXCEPT_PAGE_FAULT
2356 SetLastError(STATUS_ACCESS_VIOLATION);
2357 ret = FALSE;
2359 __ENDTRY
2360 return ret;
2363 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
2364 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2365 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2367 BOOL val = *(const BOOL *)pvStructInfo, ret;
2369 TRACE("%d\n", val);
2371 if (!pbEncoded)
2373 *pcbEncoded = 3;
2374 ret = TRUE;
2376 else if (*pcbEncoded < 3)
2378 *pcbEncoded = 3;
2379 SetLastError(ERROR_MORE_DATA);
2380 ret = FALSE;
2382 else
2384 *pcbEncoded = 3;
2385 *pbEncoded++ = ASN_BOOL;
2386 *pbEncoded++ = 1;
2387 *pbEncoded++ = val ? 0xff : 0;
2388 ret = TRUE;
2390 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2391 return ret;
2394 static BOOL WINAPI CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType,
2395 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2396 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2398 const CERT_ALT_NAME_ENTRY *entry = pvStructInfo;
2399 BOOL ret;
2400 DWORD dataLen;
2401 BYTE tag;
2403 ret = TRUE;
2404 switch (entry->dwAltNameChoice)
2406 case CERT_ALT_NAME_RFC822_NAME:
2407 case CERT_ALT_NAME_DNS_NAME:
2408 case CERT_ALT_NAME_URL:
2409 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2410 if (entry->u.pwszURL)
2412 DWORD i;
2414 /* Not + 1: don't encode the NULL-terminator */
2415 dataLen = lstrlenW(entry->u.pwszURL);
2416 for (i = 0; ret && i < dataLen; i++)
2418 if (entry->u.pwszURL[i] > 0x7f)
2420 SetLastError(CRYPT_E_INVALID_IA5_STRING);
2421 ret = FALSE;
2422 *pcbEncoded = i;
2426 else
2427 dataLen = 0;
2428 break;
2429 case CERT_ALT_NAME_DIRECTORY_NAME:
2430 tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1);
2431 dataLen = entry->u.DirectoryName.cbData;
2432 break;
2433 case CERT_ALT_NAME_IP_ADDRESS:
2434 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2435 dataLen = entry->u.IPAddress.cbData;
2436 break;
2437 case CERT_ALT_NAME_REGISTERED_ID:
2439 struct AsnEncodeTagSwappedItem swapped =
2440 { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID,
2441 CRYPT_AsnEncodeOid };
2443 return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded,
2444 pcbEncoded);
2446 case CERT_ALT_NAME_OTHER_NAME:
2447 FIXME("name type %ld unimplemented\n", entry->dwAltNameChoice);
2448 return FALSE;
2449 default:
2450 SetLastError(E_INVALIDARG);
2451 return FALSE;
2453 if (ret)
2455 DWORD bytesNeeded, lenBytes;
2457 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2458 bytesNeeded = 1 + dataLen + lenBytes;
2459 if (!pbEncoded)
2460 *pcbEncoded = bytesNeeded;
2461 else if (*pcbEncoded < bytesNeeded)
2463 SetLastError(ERROR_MORE_DATA);
2464 *pcbEncoded = bytesNeeded;
2465 ret = FALSE;
2467 else
2469 *pbEncoded++ = tag;
2470 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2471 pbEncoded += lenBytes;
2472 switch (entry->dwAltNameChoice)
2474 case CERT_ALT_NAME_RFC822_NAME:
2475 case CERT_ALT_NAME_DNS_NAME:
2476 case CERT_ALT_NAME_URL:
2478 DWORD i;
2480 for (i = 0; i < dataLen; i++)
2481 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
2482 break;
2484 case CERT_ALT_NAME_DIRECTORY_NAME:
2485 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen);
2486 break;
2487 case CERT_ALT_NAME_IP_ADDRESS:
2488 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
2489 break;
2491 if (ret)
2492 *pcbEncoded = bytesNeeded;
2495 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2496 return ret;
2499 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
2500 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2501 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2503 BOOL ret;
2505 __TRY
2507 const CERT_AUTHORITY_KEY_ID_INFO *info = pvStructInfo;
2508 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2509 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2510 struct AsnConstructedItem constructed = { 0 };
2511 DWORD cItem = 0, cSwapped = 0;
2513 if (info->KeyId.cbData)
2515 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2516 swapped[cSwapped].pvStructInfo = &info->KeyId;
2517 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
2518 items[cItem].pvStructInfo = &swapped[cSwapped];
2519 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2520 cSwapped++;
2521 cItem++;
2523 if (info->CertIssuer.cbData)
2525 constructed.tag = 1;
2526 constructed.pvStructInfo = &info->CertIssuer;
2527 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2528 items[cItem].pvStructInfo = &constructed;
2529 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2530 cItem++;
2532 if (info->CertSerialNumber.cbData)
2534 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2535 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2536 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2537 items[cItem].pvStructInfo = &swapped[cSwapped];
2538 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2539 cSwapped++;
2540 cItem++;
2542 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2543 pEncodePara, pbEncoded, pcbEncoded);
2545 __EXCEPT_PAGE_FAULT
2547 SetLastError(STATUS_ACCESS_VIOLATION);
2548 ret = FALSE;
2550 __ENDTRY
2551 return ret;
2554 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2555 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2556 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2558 BOOL ret;
2560 __TRY
2562 const CERT_ALT_NAME_INFO *info = pvStructInfo;
2563 DWORD bytesNeeded, dataLen, lenBytes, i;
2565 ret = TRUE;
2566 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2567 * can't encode an erroneous entry index if it's bigger than this.
2569 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2571 DWORD len;
2573 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, NULL,
2574 &info->rgAltEntry[i], 0, NULL, NULL, &len);
2575 if (ret)
2576 dataLen += len;
2577 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2579 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2580 * the bad character, now set the index of the bad
2581 * entry
2583 *pcbEncoded = (BYTE)i <<
2584 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2587 if (ret)
2589 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2590 bytesNeeded = 1 + lenBytes + dataLen;
2591 if (!pbEncoded)
2593 *pcbEncoded = bytesNeeded;
2594 ret = TRUE;
2596 else
2598 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2599 pbEncoded, pcbEncoded, bytesNeeded)))
2601 BYTE *out;
2603 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2604 pbEncoded = *(BYTE **)pbEncoded;
2605 out = pbEncoded;
2606 *out++ = ASN_SEQUENCEOF;
2607 CRYPT_EncodeLen(dataLen, out, &lenBytes);
2608 out += lenBytes;
2609 for (i = 0; ret && i < info->cAltEntry; i++)
2611 DWORD len = dataLen;
2613 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType,
2614 NULL, &info->rgAltEntry[i], 0, NULL, out, &len);
2615 if (ret)
2617 out += len;
2618 dataLen -= len;
2621 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2622 CRYPT_FreeSpace(pEncodePara, pbEncoded);
2627 __EXCEPT_PAGE_FAULT
2629 SetLastError(STATUS_ACCESS_VIOLATION);
2630 ret = FALSE;
2632 __ENDTRY
2633 return ret;
2636 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2637 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2638 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2640 BOOL ret;
2642 __TRY
2644 const CERT_AUTHORITY_KEY_ID2_INFO *info = pvStructInfo;
2645 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2646 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2647 DWORD cItem = 0, cSwapped = 0;
2649 if (info->KeyId.cbData)
2651 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2652 swapped[cSwapped].pvStructInfo = &info->KeyId;
2653 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
2654 items[cItem].pvStructInfo = &swapped[cSwapped];
2655 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2656 cSwapped++;
2657 cItem++;
2659 if (info->AuthorityCertIssuer.cAltEntry)
2661 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2662 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2663 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2664 items[cItem].pvStructInfo = &swapped[cSwapped];
2665 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2666 cSwapped++;
2667 cItem++;
2669 if (info->AuthorityCertSerialNumber.cbData)
2671 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2672 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2673 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2674 items[cItem].pvStructInfo = &swapped[cSwapped];
2675 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2676 cSwapped++;
2677 cItem++;
2679 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2680 pEncodePara, pbEncoded, pcbEncoded);
2682 __EXCEPT_PAGE_FAULT
2684 SetLastError(STATUS_ACCESS_VIOLATION);
2685 ret = FALSE;
2687 __ENDTRY
2688 return ret;
2691 static BOOL CRYPT_AsnEncodeAccessDescription(
2692 const CERT_ACCESS_DESCRIPTION *descr, BYTE *pbEncoded, DWORD *pcbEncoded)
2694 struct AsnEncodeSequenceItem items[] = {
2695 { descr->pszAccessMethod, CRYPT_AsnEncodeOid, 0 },
2696 { &descr->AccessLocation, CRYPT_AsnEncodeAltNameEntry, 0 },
2699 if (!descr->pszAccessMethod)
2701 SetLastError(E_INVALIDARG);
2702 return FALSE;
2704 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, ARRAY_SIZE(items), 0, NULL, pbEncoded, pcbEncoded);
2707 static BOOL WINAPI CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType,
2708 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2709 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2711 BOOL ret;
2713 __TRY
2715 DWORD bytesNeeded, dataLen, lenBytes, i;
2716 const CERT_AUTHORITY_INFO_ACCESS *info = pvStructInfo;
2718 ret = TRUE;
2719 for (i = 0, dataLen = 0; ret && i < info->cAccDescr; i++)
2721 DWORD size;
2723 ret = CRYPT_AsnEncodeAccessDescription(&info->rgAccDescr[i], NULL,
2724 &size);
2725 if (ret)
2726 dataLen += size;
2728 if (ret)
2730 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2731 bytesNeeded = 1 + lenBytes + dataLen;
2732 if (!pbEncoded)
2733 *pcbEncoded = bytesNeeded;
2734 else
2736 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2737 pbEncoded, pcbEncoded, bytesNeeded)))
2739 BYTE *out;
2741 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2742 pbEncoded = *(BYTE **)pbEncoded;
2743 out = pbEncoded;
2744 *out++ = ASN_SEQUENCEOF;
2745 CRYPT_EncodeLen(dataLen, out, &lenBytes);
2746 out += lenBytes;
2747 for (i = 0; i < info->cAccDescr; i++)
2749 DWORD size = dataLen;
2751 ret = CRYPT_AsnEncodeAccessDescription(
2752 &info->rgAccDescr[i], out, &size);
2753 out += size;
2754 dataLen -= size;
2756 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2757 CRYPT_FreeSpace(pEncodePara, pbEncoded);
2762 __EXCEPT_PAGE_FAULT
2764 SetLastError(STATUS_ACCESS_VIOLATION);
2765 ret = FALSE;
2767 __ENDTRY
2768 return ret;
2771 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2772 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2773 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2775 BOOL ret;
2777 __TRY
2779 const CERT_BASIC_CONSTRAINTS_INFO *info = pvStructInfo;
2780 struct AsnEncodeSequenceItem items[3] = {
2781 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2782 { 0 }
2784 DWORD cItem = 1;
2786 if (info->fPathLenConstraint)
2788 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2789 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2790 cItem++;
2792 if (info->cSubtreesConstraint)
2794 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2795 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2796 cItem++;
2798 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2799 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2801 __EXCEPT_PAGE_FAULT
2803 SetLastError(STATUS_ACCESS_VIOLATION);
2804 ret = FALSE;
2806 __ENDTRY
2807 return ret;
2810 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2811 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2812 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2814 BOOL ret;
2816 __TRY
2818 const CERT_BASIC_CONSTRAINTS2_INFO *info = pvStructInfo;
2819 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2820 DWORD cItem = 0;
2822 if (info->fCA)
2824 items[cItem].pvStructInfo = &info->fCA;
2825 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2826 cItem++;
2828 if (info->fPathLenConstraint)
2830 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2831 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2832 cItem++;
2834 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2835 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2837 __EXCEPT_PAGE_FAULT
2839 SetLastError(STATUS_ACCESS_VIOLATION);
2840 ret = FALSE;
2842 __ENDTRY
2843 return ret;
2846 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType,
2847 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2848 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2850 const CERT_POLICY_INFO *info = pvStructInfo;
2851 BOOL ret;
2853 if (!info->cPolicyQualifier)
2855 *pcbEncoded = 0;
2856 ret = TRUE;
2858 else
2860 struct AsnEncodeSequenceItem items[2] = {
2861 { NULL, CRYPT_AsnEncodeOid, 0 },
2862 { NULL, CRYPT_CopyEncodedBlob, 0 },
2864 DWORD bytesNeeded = 0, lenBytes, size, i;
2866 ret = TRUE;
2867 for (i = 0; ret && i < info->cPolicyQualifier; i++)
2869 items[0].pvStructInfo =
2870 info->rgPolicyQualifier[i].pszPolicyQualifierId;
2871 items[1].pvStructInfo = &info->rgPolicyQualifier[i].Qualifier;
2872 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items),
2873 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
2874 if (ret)
2875 bytesNeeded += size;
2877 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2878 bytesNeeded += 1 + lenBytes;
2879 if (ret)
2881 if (!pbEncoded)
2882 *pcbEncoded = bytesNeeded;
2883 else
2885 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2886 pbEncoded, pcbEncoded, bytesNeeded)))
2888 BYTE *out;
2890 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2891 pbEncoded = *(BYTE **)pbEncoded;
2892 out = pbEncoded;
2893 *out++ = ASN_SEQUENCEOF;
2894 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
2895 out += lenBytes;
2896 for (i = 0; ret && i < info->cPolicyQualifier; i++)
2898 items[0].pvStructInfo =
2899 info->rgPolicyQualifier[i].pszPolicyQualifierId;
2900 items[1].pvStructInfo =
2901 &info->rgPolicyQualifier[i].Qualifier;
2902 size = bytesNeeded;
2903 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items),
2904 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, out, &size);
2905 if (ret)
2907 out += size;
2908 bytesNeeded -= size;
2911 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2912 CRYPT_FreeSpace(pEncodePara, pbEncoded);
2917 return ret;
2920 static BOOL CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType,
2921 const CERT_POLICY_INFO *info, DWORD dwFlags, BYTE *pbEncoded,
2922 DWORD *pcbEncoded)
2924 struct AsnEncodeSequenceItem items[2] = {
2925 { info->pszPolicyIdentifier, CRYPT_AsnEncodeOid, 0 },
2926 { info, CRYPT_AsnEncodeCertPolicyQualifiers, 0 },
2928 BOOL ret;
2930 if (!info->pszPolicyIdentifier)
2932 SetLastError(E_INVALIDARG);
2933 return FALSE;
2935 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items), dwFlags, NULL, pbEncoded, pcbEncoded);
2936 return ret;
2939 static BOOL WINAPI CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType,
2940 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2941 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2943 BOOL ret = FALSE;
2945 __TRY
2947 const CERT_POLICIES_INFO *info = pvStructInfo;
2948 DWORD bytesNeeded = 0, lenBytes, size, i;
2950 ret = TRUE;
2951 for (i = 0; ret && i < info->cPolicyInfo; i++)
2953 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
2954 &info->rgPolicyInfo[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
2955 &size);
2956 if (ret)
2957 bytesNeeded += size;
2959 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2960 bytesNeeded += 1 + lenBytes;
2961 if (ret)
2963 if (!pbEncoded)
2964 *pcbEncoded = bytesNeeded;
2965 else
2967 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2968 pbEncoded, pcbEncoded, bytesNeeded)))
2970 BYTE *out;
2972 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2973 pbEncoded = *(BYTE **)pbEncoded;
2974 out = pbEncoded;
2975 *out++ = ASN_SEQUENCEOF;
2976 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
2977 out += lenBytes;
2978 for (i = 0; ret && i < info->cPolicyInfo; i++)
2980 size = bytesNeeded;
2981 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
2982 &info->rgPolicyInfo[i],
2983 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, out, &size);
2984 if (ret)
2986 out += size;
2987 bytesNeeded -= size;
2990 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2991 CRYPT_FreeSpace(pEncodePara, pbEncoded);
2996 __EXCEPT_PAGE_FAULT
2998 SetLastError(STATUS_ACCESS_VIOLATION);
3000 __ENDTRY
3001 return ret;
3004 static BOOL CRYPT_AsnEncodeCertPolicyMapping(DWORD dwCertEncodingType,
3005 const CERT_POLICY_MAPPING *mapping, DWORD dwFlags, BYTE *pbEncoded,
3006 DWORD *pcbEncoded)
3008 struct AsnEncodeSequenceItem items[] = {
3009 { mapping->pszIssuerDomainPolicy, CRYPT_AsnEncodeOid, 0 },
3010 { mapping->pszSubjectDomainPolicy, CRYPT_AsnEncodeOid, 0 },
3013 if (!mapping->pszIssuerDomainPolicy || !mapping->pszSubjectDomainPolicy)
3015 SetLastError(E_INVALIDARG);
3016 return FALSE;
3018 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items), dwFlags, NULL, pbEncoded, pcbEncoded);
3021 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyMappings(DWORD dwCertEncodingType,
3022 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3023 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3025 BOOL ret = FALSE;
3027 __TRY
3029 const CERT_POLICY_MAPPINGS_INFO *info = pvStructInfo;
3030 DWORD bytesNeeded = 0, lenBytes, size, i;
3032 ret = TRUE;
3033 for (i = 0; ret && i < info->cPolicyMapping; i++)
3035 ret = CRYPT_AsnEncodeCertPolicyMapping(dwCertEncodingType,
3036 &info->rgPolicyMapping[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
3037 NULL, &size);
3038 if (ret)
3039 bytesNeeded += size;
3041 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3042 bytesNeeded += 1 + lenBytes;
3043 if (ret)
3045 if (!pbEncoded)
3046 *pcbEncoded = bytesNeeded;
3047 else
3049 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3050 pbEncoded, pcbEncoded, bytesNeeded)))
3052 BYTE *out;
3054 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3055 pbEncoded = *(BYTE **)pbEncoded;
3056 out = pbEncoded;
3057 *out++ = ASN_SEQUENCEOF;
3058 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
3059 out += lenBytes;
3060 for (i = 0; ret && i < info->cPolicyMapping; i++)
3062 size = bytesNeeded;
3063 ret = CRYPT_AsnEncodeCertPolicyMapping(
3064 dwCertEncodingType, &info->rgPolicyMapping[i],
3065 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, out, &size);
3066 if (ret)
3068 out += size;
3069 bytesNeeded -= size;
3072 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
3073 CRYPT_FreeSpace(pEncodePara, pbEncoded);
3078 __EXCEPT_PAGE_FAULT
3080 SetLastError(STATUS_ACCESS_VIOLATION);
3082 __ENDTRY
3083 return ret;
3086 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyConstraints(
3087 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3088 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3089 DWORD *pcbEncoded)
3091 BOOL ret = FALSE;
3093 __TRY
3095 const CERT_POLICY_CONSTRAINTS_INFO *info = pvStructInfo;
3096 struct AsnEncodeSequenceItem items[2];
3097 struct AsnEncodeTagSwappedItem swapped[2];
3098 DWORD cItem = 0, cSwapped = 0;
3100 if (info->fRequireExplicitPolicy)
3102 swapped[cSwapped].tag = ASN_CONTEXT | 0;
3103 swapped[cSwapped].pvStructInfo =
3104 &info->dwRequireExplicitPolicySkipCerts;
3105 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3106 items[cItem].pvStructInfo = &swapped[cSwapped];
3107 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3108 cSwapped++;
3109 cItem++;
3111 if (info->fInhibitPolicyMapping)
3113 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3114 swapped[cSwapped].pvStructInfo =
3115 &info->dwInhibitPolicyMappingSkipCerts;
3116 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3117 items[cItem].pvStructInfo = &swapped[cSwapped];
3118 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3119 cSwapped++;
3120 cItem++;
3122 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3123 dwFlags, NULL, pbEncoded, pcbEncoded);
3125 __EXCEPT_PAGE_FAULT
3127 SetLastError(STATUS_ACCESS_VIOLATION);
3129 __ENDTRY
3130 return ret;
3133 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey_Bcrypt(DWORD dwCertEncodingType,
3134 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3135 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3137 BOOL ret;
3139 __TRY
3141 const BCRYPT_RSAKEY_BLOB *hdr = pvStructInfo;
3143 BYTE *pubexp = (BYTE*)pvStructInfo + sizeof(BCRYPT_RSAKEY_BLOB);
3144 BYTE *modulus = (BYTE*)pvStructInfo + sizeof(BCRYPT_RSAKEY_BLOB) + hdr->cbPublicExp;
3145 BYTE *pubexp_be = CryptMemAlloc(hdr->cbPublicExp);
3146 BYTE *modulus_be = CryptMemAlloc(hdr->cbModulus);
3147 CRYPT_INTEGER_BLOB pubexp_int = { hdr->cbPublicExp, pubexp_be };
3148 CRYPT_INTEGER_BLOB modulus_int = { hdr->cbModulus, modulus_be};
3150 struct AsnEncodeSequenceItem items[] = {
3151 { &modulus_int, CRYPT_AsnEncodeUnsignedInteger, 0 },
3152 { &pubexp_int, CRYPT_AsnEncodeInteger, 0 },
3155 /* CNG_RSA_PUBLIC_KEY_BLOB stores the exponent and modulus
3156 * in big-endian format, so we need to convert them
3157 * to little-endian format before encoding
3159 CRYPT_CopyReversed(pubexp_be, pubexp, hdr->cbPublicExp);
3160 CRYPT_CopyReversed(modulus_be, modulus, hdr->cbModulus);
3162 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3163 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3165 CryptMemFree(pubexp_be);
3166 CryptMemFree(modulus_be);
3168 __EXCEPT_PAGE_FAULT
3170 SetLastError(STATUS_ACCESS_VIOLATION);
3171 ret = FALSE;
3173 __ENDTRY
3174 return ret;
3179 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
3180 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3181 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3183 BOOL ret;
3185 __TRY
3187 const BLOBHEADER *hdr = pvStructInfo;
3189 if (hdr->bType != PUBLICKEYBLOB)
3191 SetLastError(E_INVALIDARG);
3192 ret = FALSE;
3194 else
3196 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
3197 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
3198 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
3199 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
3200 struct AsnEncodeSequenceItem items[] = {
3201 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
3202 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
3205 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3206 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3209 __EXCEPT_PAGE_FAULT
3211 SetLastError(STATUS_ACCESS_VIOLATION);
3212 ret = FALSE;
3214 __ENDTRY
3215 return ret;
3218 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
3219 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3220 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3222 BOOL ret;
3224 __TRY
3226 const CRYPT_DATA_BLOB *blob = pvStructInfo;
3227 DWORD bytesNeeded, lenBytes;
3229 TRACE("(%ld, %p), %08lx, %p, %p, %ld\n", blob->cbData, blob->pbData,
3230 dwFlags, pEncodePara, pbEncoded, pbEncoded ? *pcbEncoded : 0);
3232 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
3233 bytesNeeded = 1 + lenBytes + blob->cbData;
3234 if (!pbEncoded)
3236 *pcbEncoded = bytesNeeded;
3237 ret = TRUE;
3239 else
3241 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3242 pcbEncoded, bytesNeeded)))
3244 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3245 pbEncoded = *(BYTE **)pbEncoded;
3246 *pbEncoded++ = ASN_OCTETSTRING;
3247 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
3248 pbEncoded += lenBytes;
3249 if (blob->cbData)
3250 memcpy(pbEncoded, blob->pbData, blob->cbData);
3254 __EXCEPT_PAGE_FAULT
3256 SetLastError(STATUS_ACCESS_VIOLATION);
3257 ret = FALSE;
3259 __ENDTRY
3260 TRACE("returning %d (%08lx)\n", ret, GetLastError());
3261 return ret;
3264 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
3265 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3266 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3268 BOOL ret;
3270 __TRY
3272 const CRYPT_BIT_BLOB *blob = pvStructInfo;
3273 DWORD bytesNeeded, lenBytes, dataBytes;
3274 BYTE unusedBits;
3276 /* yep, MS allows cUnusedBits to be >= 8 */
3277 if (!blob->cUnusedBits)
3279 dataBytes = blob->cbData;
3280 unusedBits = 0;
3282 else if (blob->cbData * 8 > blob->cUnusedBits)
3284 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
3285 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
3286 blob->cUnusedBits;
3288 else
3290 dataBytes = 0;
3291 unusedBits = 0;
3293 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
3294 bytesNeeded = 1 + lenBytes + dataBytes + 1;
3295 if (!pbEncoded)
3297 *pcbEncoded = bytesNeeded;
3298 ret = TRUE;
3300 else
3302 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3303 pcbEncoded, bytesNeeded)))
3305 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3306 pbEncoded = *(BYTE **)pbEncoded;
3307 *pbEncoded++ = ASN_BITSTRING;
3308 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
3309 pbEncoded += lenBytes;
3310 *pbEncoded++ = unusedBits;
3311 if (dataBytes)
3313 BYTE mask = 0xff << unusedBits;
3315 if (dataBytes > 1)
3317 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
3318 pbEncoded += dataBytes - 1;
3320 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
3325 __EXCEPT_PAGE_FAULT
3327 SetLastError(STATUS_ACCESS_VIOLATION);
3328 ret = FALSE;
3330 __ENDTRY
3331 return ret;
3334 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
3335 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3336 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3338 BOOL ret;
3340 __TRY
3342 const CRYPT_BIT_BLOB *blob = pvStructInfo;
3343 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
3345 ret = TRUE;
3346 if (newBlob.cbData)
3348 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
3349 if (newBlob.pbData)
3351 DWORD i;
3353 for (i = 0; i < newBlob.cbData; i++)
3354 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
3356 else
3357 ret = FALSE;
3359 if (ret)
3360 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
3361 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3362 CryptMemFree(newBlob.pbData);
3364 __EXCEPT_PAGE_FAULT
3366 SetLastError(STATUS_ACCESS_VIOLATION);
3367 ret = FALSE;
3369 __ENDTRY
3370 return ret;
3373 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
3374 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3375 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3377 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
3379 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
3380 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3383 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
3384 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3385 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3387 BOOL ret;
3389 __TRY
3391 DWORD significantBytes, lenBytes, bytesNeeded;
3392 BYTE padByte = 0;
3393 BOOL pad = FALSE;
3394 const CRYPT_INTEGER_BLOB *blob = pvStructInfo;
3396 significantBytes = blob->cbData;
3397 if (significantBytes)
3399 if (blob->pbData[significantBytes - 1] & 0x80)
3401 /* negative, lop off leading (little-endian) 0xffs */
3402 for (; significantBytes > 0 &&
3403 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
3405 if (blob->pbData[significantBytes - 1] < 0x80)
3407 padByte = 0xff;
3408 pad = TRUE;
3411 else
3413 /* positive, lop off leading (little-endian) zeroes */
3414 for (; significantBytes > 0 &&
3415 !blob->pbData[significantBytes - 1]; significantBytes--)
3417 if (significantBytes == 0)
3418 significantBytes = 1;
3419 if (blob->pbData[significantBytes - 1] > 0x7f)
3421 padByte = 0;
3422 pad = TRUE;
3426 if (pad)
3427 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3428 else
3429 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3430 bytesNeeded = 1 + lenBytes + significantBytes;
3431 if (pad)
3432 bytesNeeded++;
3433 if (!pbEncoded)
3435 *pcbEncoded = bytesNeeded;
3436 ret = TRUE;
3438 else
3440 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3441 pcbEncoded, bytesNeeded)))
3443 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3444 pbEncoded = *(BYTE **)pbEncoded;
3445 *pbEncoded++ = ASN_INTEGER;
3446 if (pad)
3448 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3449 pbEncoded += lenBytes;
3450 *pbEncoded++ = padByte;
3452 else
3454 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3455 pbEncoded += lenBytes;
3457 for (; significantBytes > 0; significantBytes--)
3458 *(pbEncoded++) = blob->pbData[significantBytes - 1];
3462 __EXCEPT_PAGE_FAULT
3464 SetLastError(STATUS_ACCESS_VIOLATION);
3465 ret = FALSE;
3467 __ENDTRY
3468 return ret;
3471 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
3472 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3473 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3475 BOOL ret;
3477 __TRY
3479 DWORD significantBytes, lenBytes, bytesNeeded;
3480 BOOL pad = FALSE;
3481 const CRYPT_INTEGER_BLOB *blob = pvStructInfo;
3483 significantBytes = blob->cbData;
3484 if (significantBytes)
3486 /* positive, lop off leading (little-endian) zeroes */
3487 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
3488 significantBytes--)
3490 if (significantBytes == 0)
3491 significantBytes = 1;
3492 if (blob->pbData[significantBytes - 1] > 0x7f)
3493 pad = TRUE;
3495 if (pad)
3496 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3497 else
3498 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3499 bytesNeeded = 1 + lenBytes + significantBytes;
3500 if (pad)
3501 bytesNeeded++;
3502 if (!pbEncoded)
3504 *pcbEncoded = bytesNeeded;
3505 ret = TRUE;
3507 else
3509 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3510 pcbEncoded, bytesNeeded)))
3512 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3513 pbEncoded = *(BYTE **)pbEncoded;
3514 *pbEncoded++ = ASN_INTEGER;
3515 if (pad)
3517 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3518 pbEncoded += lenBytes;
3519 *pbEncoded++ = 0;
3521 else
3523 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3524 pbEncoded += lenBytes;
3526 for (; significantBytes > 0; significantBytes--)
3527 *(pbEncoded++) = blob->pbData[significantBytes - 1];
3531 __EXCEPT_PAGE_FAULT
3533 SetLastError(STATUS_ACCESS_VIOLATION);
3534 ret = FALSE;
3536 __ENDTRY
3537 return ret;
3540 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
3541 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3542 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3544 CRYPT_INTEGER_BLOB blob;
3545 BOOL ret;
3547 /* Encode as an unsigned integer, then change the tag to enumerated */
3548 blob.cbData = sizeof(DWORD);
3549 blob.pbData = (BYTE *)pvStructInfo;
3550 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
3551 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3552 if (ret && pbEncoded)
3554 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3555 pbEncoded = *(BYTE **)pbEncoded;
3556 pbEncoded[0] = ASN_ENUMERATED;
3558 return ret;
3561 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
3562 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3563 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3565 BOOL ret;
3567 __TRY
3569 SYSTEMTIME sysTime;
3570 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ. I use a
3571 * temporary buffer because the output buffer is not NULL-terminated.
3573 static const DWORD bytesNeeded = 15;
3574 char buf[40];
3576 if (!pbEncoded)
3578 *pcbEncoded = bytesNeeded;
3579 ret = TRUE;
3581 else
3583 /* Sanity check the year, this is a two-digit year format */
3584 ret = FileTimeToSystemTime(pvStructInfo, &sysTime);
3585 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
3587 SetLastError(CRYPT_E_BAD_ENCODE);
3588 ret = FALSE;
3590 if (ret)
3592 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3593 pbEncoded, pcbEncoded, bytesNeeded)))
3595 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3596 pbEncoded = *(BYTE **)pbEncoded;
3597 buf[0] = ASN_UTCTIME;
3598 buf[1] = bytesNeeded - 2;
3599 snprintf(buf + 2, sizeof(buf) - 2,
3600 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
3601 sysTime.wYear - 2000 : sysTime.wYear - 1900,
3602 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3603 sysTime.wMinute, sysTime.wSecond);
3604 memcpy(pbEncoded, buf, bytesNeeded);
3609 __EXCEPT_PAGE_FAULT
3611 SetLastError(STATUS_ACCESS_VIOLATION);
3612 ret = FALSE;
3614 __ENDTRY
3615 return ret;
3618 static BOOL CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
3619 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3620 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3622 BOOL ret;
3624 __TRY
3626 SYSTEMTIME sysTime;
3627 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ. I use a
3628 * temporary buffer because the output buffer is not NULL-terminated.
3630 static const DWORD bytesNeeded = 17;
3631 char buf[40];
3633 if (!pbEncoded)
3635 *pcbEncoded = bytesNeeded;
3636 ret = TRUE;
3638 else
3640 ret = FileTimeToSystemTime(pvStructInfo, &sysTime);
3641 if (ret)
3642 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3643 pcbEncoded, bytesNeeded);
3644 if (ret)
3646 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3647 pbEncoded = *(BYTE **)pbEncoded;
3648 buf[0] = ASN_GENERALTIME;
3649 buf[1] = bytesNeeded - 2;
3650 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
3651 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3652 sysTime.wMinute, sysTime.wSecond);
3653 memcpy(pbEncoded, buf, bytesNeeded);
3657 __EXCEPT_PAGE_FAULT
3659 SetLastError(STATUS_ACCESS_VIOLATION);
3660 ret = FALSE;
3662 __ENDTRY
3663 return ret;
3666 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
3667 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3668 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3670 BOOL ret;
3672 __TRY
3674 SYSTEMTIME sysTime;
3676 /* Check the year, if it's in the UTCTime range call that encode func */
3677 if (!FileTimeToSystemTime(pvStructInfo, &sysTime))
3678 return FALSE;
3679 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
3680 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
3681 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3682 else
3683 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
3684 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
3685 pcbEncoded);
3687 __EXCEPT_PAGE_FAULT
3689 SetLastError(STATUS_ACCESS_VIOLATION);
3690 ret = FALSE;
3692 __ENDTRY
3693 return ret;
3696 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
3697 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3698 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3700 BOOL ret;
3702 __TRY
3704 DWORD bytesNeeded, dataLen, lenBytes, i;
3705 const CRYPT_SEQUENCE_OF_ANY *seq = pvStructInfo;
3707 for (i = 0, dataLen = 0; i < seq->cValue; i++)
3708 dataLen += seq->rgValue[i].cbData;
3709 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3710 bytesNeeded = 1 + lenBytes + dataLen;
3711 if (!pbEncoded)
3713 *pcbEncoded = bytesNeeded;
3714 ret = TRUE;
3716 else
3718 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3719 pcbEncoded, bytesNeeded)))
3721 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3722 pbEncoded = *(BYTE **)pbEncoded;
3723 *pbEncoded++ = ASN_SEQUENCEOF;
3724 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
3725 pbEncoded += lenBytes;
3726 for (i = 0; i < seq->cValue; i++)
3728 memcpy(pbEncoded, seq->rgValue[i].pbData,
3729 seq->rgValue[i].cbData);
3730 pbEncoded += seq->rgValue[i].cbData;
3735 __EXCEPT_PAGE_FAULT
3737 SetLastError(STATUS_ACCESS_VIOLATION);
3738 ret = FALSE;
3740 __ENDTRY
3741 return ret;
3744 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
3745 BYTE *pbEncoded, DWORD *pcbEncoded)
3747 BOOL ret = TRUE;
3748 struct AsnEncodeSequenceItem items[3] = { { 0 } };
3749 struct AsnConstructedItem constructed = { 0 };
3750 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
3751 DWORD cItem = 0, cSwapped = 0;
3753 switch (distPoint->DistPointName.dwDistPointNameChoice)
3755 case CRL_DIST_POINT_NO_NAME:
3756 /* do nothing */
3757 break;
3758 case CRL_DIST_POINT_FULL_NAME:
3759 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3760 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
3761 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3762 constructed.tag = 0;
3763 constructed.pvStructInfo = &swapped[cSwapped];
3764 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3765 items[cItem].pvStructInfo = &constructed;
3766 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3767 cSwapped++;
3768 cItem++;
3769 break;
3770 case CRL_DIST_POINT_ISSUER_RDN_NAME:
3771 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3772 ret = FALSE;
3773 break;
3774 default:
3775 ret = FALSE;
3777 if (ret && distPoint->ReasonFlags.cbData)
3779 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3780 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
3781 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3782 items[cItem].pvStructInfo = &swapped[cSwapped];
3783 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3784 cSwapped++;
3785 cItem++;
3787 if (ret && distPoint->CRLIssuer.cAltEntry)
3789 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
3790 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
3791 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3792 items[cItem].pvStructInfo = &swapped[cSwapped];
3793 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3794 cSwapped++;
3795 cItem++;
3797 if (ret)
3798 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
3799 pbEncoded, pcbEncoded);
3800 return ret;
3803 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
3804 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3805 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3807 BOOL ret;
3809 __TRY
3811 const CRL_DIST_POINTS_INFO *info = pvStructInfo;
3813 if (!info->cDistPoint)
3815 SetLastError(E_INVALIDARG);
3816 ret = FALSE;
3818 else
3820 DWORD bytesNeeded, dataLen, lenBytes, i;
3822 ret = TRUE;
3823 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
3825 DWORD len;
3827 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
3828 &len);
3829 if (ret)
3830 dataLen += len;
3831 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
3833 /* Have to propagate index of failing character */
3834 *pcbEncoded = len;
3837 if (ret)
3839 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3840 bytesNeeded = 1 + lenBytes + dataLen;
3841 if (!pbEncoded)
3843 *pcbEncoded = bytesNeeded;
3844 ret = TRUE;
3846 else
3848 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3849 pbEncoded, pcbEncoded, bytesNeeded)))
3851 BYTE *out;
3853 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3854 pbEncoded = *(BYTE **)pbEncoded;
3855 out = pbEncoded;
3856 *out++ = ASN_SEQUENCEOF;
3857 CRYPT_EncodeLen(dataLen, out, &lenBytes);
3858 out += lenBytes;
3859 for (i = 0; ret && i < info->cDistPoint; i++)
3861 DWORD len = dataLen;
3863 ret = CRYPT_AsnEncodeDistPoint(
3864 &info->rgDistPoint[i], out, &len);
3865 if (ret)
3867 out += len;
3868 dataLen -= len;
3871 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
3872 CRYPT_FreeSpace(pEncodePara, pbEncoded);
3878 __EXCEPT_PAGE_FAULT
3880 SetLastError(STATUS_ACCESS_VIOLATION);
3881 ret = FALSE;
3883 __ENDTRY
3884 return ret;
3887 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3888 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3889 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3891 BOOL ret;
3893 __TRY
3895 const CERT_ENHKEY_USAGE *usage = pvStructInfo;
3896 DWORD bytesNeeded = 0, lenBytes, size, i;
3898 ret = TRUE;
3899 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3901 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3902 usage->rgpszUsageIdentifier[i],
3903 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
3904 if (ret)
3905 bytesNeeded += size;
3907 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3908 bytesNeeded += 1 + lenBytes;
3909 if (ret)
3911 if (!pbEncoded)
3912 *pcbEncoded = bytesNeeded;
3913 else
3915 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3916 pbEncoded, pcbEncoded, bytesNeeded)))
3918 BYTE *out;
3920 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3921 pbEncoded = *(BYTE **)pbEncoded;
3922 out = pbEncoded;
3923 *out++ = ASN_SEQUENCEOF;
3924 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
3925 out += lenBytes;
3926 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3928 size = bytesNeeded;
3929 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3930 usage->rgpszUsageIdentifier[i],
3931 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, out, &size);
3932 if (ret)
3934 out += size;
3935 bytesNeeded -= size;
3938 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
3939 CRYPT_FreeSpace(pEncodePara, pbEncoded);
3944 __EXCEPT_PAGE_FAULT
3946 SetLastError(STATUS_ACCESS_VIOLATION);
3947 ret = FALSE;
3949 __ENDTRY
3950 return ret;
3953 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
3954 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3955 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3957 BOOL ret;
3959 __TRY
3961 const CRL_ISSUING_DIST_POINT *point = pvStructInfo;
3962 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3963 struct AsnConstructedItem constructed = { 0 };
3964 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3965 DWORD cItem = 0, cSwapped = 0;
3967 ret = TRUE;
3968 switch (point->DistPointName.dwDistPointNameChoice)
3970 case CRL_DIST_POINT_NO_NAME:
3971 /* do nothing */
3972 break;
3973 case CRL_DIST_POINT_FULL_NAME:
3974 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3975 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3976 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3977 constructed.tag = 0;
3978 constructed.pvStructInfo = &swapped[cSwapped];
3979 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3980 items[cItem].pvStructInfo = &constructed;
3981 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3982 cSwapped++;
3983 cItem++;
3984 break;
3985 default:
3986 SetLastError(E_INVALIDARG);
3987 ret = FALSE;
3989 if (ret && point->fOnlyContainsUserCerts)
3991 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3992 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3993 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3994 items[cItem].pvStructInfo = &swapped[cSwapped];
3995 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3996 cSwapped++;
3997 cItem++;
3999 if (ret && point->fOnlyContainsCACerts)
4001 swapped[cSwapped].tag = ASN_CONTEXT | 2;
4002 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
4003 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
4004 items[cItem].pvStructInfo = &swapped[cSwapped];
4005 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4006 cSwapped++;
4007 cItem++;
4009 if (ret && point->OnlySomeReasonFlags.cbData)
4011 swapped[cSwapped].tag = ASN_CONTEXT | 3;
4012 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
4013 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
4014 items[cItem].pvStructInfo = &swapped[cSwapped];
4015 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4016 cSwapped++;
4017 cItem++;
4019 if (ret && point->fIndirectCRL)
4021 swapped[cSwapped].tag = ASN_CONTEXT | 4;
4022 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
4023 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
4024 items[cItem].pvStructInfo = &swapped[cSwapped];
4025 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4026 cSwapped++;
4027 cItem++;
4029 if (ret)
4030 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4031 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4033 __EXCEPT_PAGE_FAULT
4035 SetLastError(STATUS_ACCESS_VIOLATION);
4036 ret = FALSE;
4038 __ENDTRY
4039 return ret;
4042 static BOOL CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType,
4043 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4044 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4046 BOOL ret;
4047 const CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
4048 struct AsnEncodeSequenceItem items[3] = {
4049 { &subtree->Base, CRYPT_AsnEncodeAltNameEntry, 0 },
4050 { 0 }
4052 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4053 DWORD cItem = 1, cSwapped = 0;
4055 if (subtree->dwMinimum)
4057 swapped[cSwapped].tag = ASN_CONTEXT | 0;
4058 swapped[cSwapped].pvStructInfo = &subtree->dwMinimum;
4059 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
4060 items[cItem].pvStructInfo = &swapped[cSwapped];
4061 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4062 cSwapped++;
4063 cItem++;
4065 if (subtree->fMaximum)
4067 swapped[cSwapped].tag = ASN_CONTEXT | 1;
4068 swapped[cSwapped].pvStructInfo = &subtree->dwMaximum;
4069 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
4070 items[cItem].pvStructInfo = &swapped[cSwapped];
4071 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4072 cSwapped++;
4073 cItem++;
4075 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags,
4076 pEncodePara, pbEncoded, pcbEncoded);
4077 return ret;
4080 static BOOL WINAPI CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType,
4081 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4082 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4084 BOOL ret = FALSE;
4085 CRYPT_BLOB_ARRAY permitted = { 0, NULL }, excluded = { 0, NULL };
4087 TRACE("%p\n", pvStructInfo);
4089 __TRY
4091 const CERT_NAME_CONSTRAINTS_INFO *constraints = pvStructInfo;
4092 struct AsnEncodeSequenceItem items[2] = { { 0 } };
4093 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4094 DWORD i, cItem = 0, cSwapped = 0;
4096 ret = TRUE;
4097 if (constraints->cPermittedSubtree)
4099 permitted.rgBlob = CryptMemAlloc(
4100 constraints->cPermittedSubtree * sizeof(CRYPT_DER_BLOB));
4101 if (permitted.rgBlob)
4103 permitted.cBlob = constraints->cPermittedSubtree;
4104 memset(permitted.rgBlob, 0,
4105 permitted.cBlob * sizeof(CRYPT_DER_BLOB));
4106 for (i = 0; ret && i < permitted.cBlob; i++)
4107 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
4108 NULL, &constraints->rgPermittedSubtree[i],
4109 CRYPT_ENCODE_ALLOC_FLAG, NULL,
4110 (BYTE *)&permitted.rgBlob[i].pbData,
4111 &permitted.rgBlob[i].cbData);
4112 if (ret)
4114 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4115 swapped[cSwapped].pvStructInfo = &permitted;
4116 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
4117 items[cItem].pvStructInfo = &swapped[cSwapped];
4118 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4119 cSwapped++;
4120 cItem++;
4123 else
4124 ret = FALSE;
4126 if (constraints->cExcludedSubtree)
4128 excluded.rgBlob = CryptMemAlloc(
4129 constraints->cExcludedSubtree * sizeof(CRYPT_DER_BLOB));
4130 if (excluded.rgBlob)
4132 excluded.cBlob = constraints->cExcludedSubtree;
4133 memset(excluded.rgBlob, 0,
4134 excluded.cBlob * sizeof(CRYPT_DER_BLOB));
4135 for (i = 0; ret && i < excluded.cBlob; i++)
4136 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
4137 NULL, &constraints->rgExcludedSubtree[i],
4138 CRYPT_ENCODE_ALLOC_FLAG, NULL,
4139 (BYTE *)&excluded.rgBlob[i].pbData,
4140 &excluded.rgBlob[i].cbData);
4141 if (ret)
4143 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4144 swapped[cSwapped].pvStructInfo = &excluded;
4145 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
4146 items[cItem].pvStructInfo = &swapped[cSwapped];
4147 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4148 cSwapped++;
4149 cItem++;
4152 else
4153 ret = FALSE;
4155 if (ret)
4156 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4157 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4158 for (i = 0; i < permitted.cBlob; i++)
4159 LocalFree(permitted.rgBlob[i].pbData);
4160 for (i = 0; i < excluded.cBlob; i++)
4161 LocalFree(excluded.rgBlob[i].pbData);
4163 __EXCEPT_PAGE_FAULT
4165 SetLastError(STATUS_ACCESS_VIOLATION);
4167 __ENDTRY
4168 CryptMemFree(permitted.rgBlob);
4169 CryptMemFree(excluded.rgBlob);
4170 TRACE("returning %d\n", ret);
4171 return ret;
4174 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
4175 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
4176 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
4177 DWORD *pcbEncoded)
4179 BOOL ret;
4180 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
4181 struct AsnEncodeSequenceItem items[] = {
4182 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
4183 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
4186 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4187 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4188 return ret;
4191 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
4192 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4193 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4195 BOOL ret = FALSE;
4197 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
4199 SetLastError(E_INVALIDARG);
4200 return FALSE;
4203 __TRY
4205 const CMSG_SIGNER_INFO *info = pvStructInfo;
4207 if (!info->Issuer.cbData)
4208 SetLastError(E_INVALIDARG);
4209 else
4211 struct AsnEncodeSequenceItem items[7] = {
4212 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4213 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
4214 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
4215 0 },
4217 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4218 DWORD cItem = 3, cSwapped = 0;
4220 if (info->AuthAttrs.cAttr)
4222 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4223 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
4224 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4225 items[cItem].pvStructInfo = &swapped[cSwapped];
4226 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4227 cSwapped++;
4228 cItem++;
4230 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
4231 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4232 cItem++;
4233 items[cItem].pvStructInfo = &info->EncryptedHash;
4234 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
4235 cItem++;
4236 if (info->UnauthAttrs.cAttr)
4238 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4239 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
4240 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4241 items[cItem].pvStructInfo = &swapped[cSwapped];
4242 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4243 cSwapped++;
4244 cItem++;
4246 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4247 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4250 __EXCEPT_PAGE_FAULT
4252 SetLastError(STATUS_ACCESS_VIOLATION);
4254 __ENDTRY
4255 return ret;
4258 static BOOL WINAPI CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType,
4259 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4260 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4262 BOOL ret = FALSE;
4264 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
4266 SetLastError(E_INVALIDARG);
4267 return FALSE;
4270 __TRY
4272 const CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
4274 if (info->SignerId.dwIdChoice != CERT_ID_ISSUER_SERIAL_NUMBER &&
4275 info->SignerId.dwIdChoice != CERT_ID_KEY_IDENTIFIER)
4276 SetLastError(E_INVALIDARG);
4277 else if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER &&
4278 !info->SignerId.u.IssuerSerialNumber.Issuer.cbData)
4279 SetLastError(E_INVALIDARG);
4280 else
4282 struct AsnEncodeSequenceItem items[7] = {
4283 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4285 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
4286 DWORD cItem = 1, cSwapped = 0;
4288 if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
4290 items[cItem].pvStructInfo =
4291 &info->SignerId.u.IssuerSerialNumber.Issuer;
4292 items[cItem].encodeFunc =
4293 CRYPT_AsnEncodeIssuerSerialNumber;
4294 cItem++;
4296 else
4298 swapped[cSwapped].tag = ASN_CONTEXT | 0;
4299 swapped[cSwapped].pvStructInfo = &info->SignerId.u.KeyId;
4300 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
4301 items[cItem].pvStructInfo = &swapped[cSwapped];
4302 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4303 cSwapped++;
4304 cItem++;
4306 items[cItem].pvStructInfo = &info->HashAlgorithm;
4307 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4308 cItem++;
4309 if (info->AuthAttrs.cAttr)
4311 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4312 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
4313 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4314 items[cItem].pvStructInfo = &swapped[cSwapped];
4315 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4316 cSwapped++;
4317 cItem++;
4319 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
4320 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4321 cItem++;
4322 items[cItem].pvStructInfo = &info->EncryptedHash;
4323 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
4324 cItem++;
4325 if (info->UnauthAttrs.cAttr)
4327 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4328 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
4329 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4330 items[cItem].pvStructInfo = &swapped[cSwapped];
4331 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4332 cSwapped++;
4333 cItem++;
4335 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4336 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4339 __EXCEPT_PAGE_FAULT
4341 SetLastError(STATUS_ACCESS_VIOLATION);
4343 __ENDTRY
4344 return ret;
4347 BOOL CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
4348 DWORD *pcbData)
4350 struct AsnEncodeSequenceItem items[7] = {
4351 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
4353 struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 };
4354 struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 };
4355 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4356 DWORD cItem = 1, cSwapped = 0;
4357 BOOL ret = TRUE;
4359 if (signedInfo->cSignerInfo)
4361 digestAlgorithmsSet.cItems = signedInfo->cSignerInfo;
4362 digestAlgorithmsSet.items = signedInfo->rgSignerInfo;
4363 digestAlgorithmsSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
4364 digestAlgorithmsSet.itemOffset =
4365 offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm);
4366 digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4367 items[cItem].pvStructInfo = &digestAlgorithmsSet;
4368 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4369 cItem++;
4371 items[cItem].pvStructInfo = &signedInfo->content;
4372 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal;
4373 cItem++;
4374 if (signedInfo->cCertEncoded)
4376 certSet.cItems = signedInfo->cCertEncoded;
4377 certSet.items = signedInfo->rgCertEncoded;
4378 certSet.itemSize = sizeof(CERT_BLOB);
4379 certSet.itemOffset = 0;
4380 certSet.encode = CRYPT_CopyEncodedBlob;
4381 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0;
4382 swapped[cSwapped].pvStructInfo = &certSet;
4383 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4384 items[cItem].pvStructInfo = &swapped[cSwapped];
4385 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4386 cSwapped++;
4387 cItem++;
4389 if (signedInfo->cCrlEncoded)
4391 crlSet.cItems = signedInfo->cCrlEncoded;
4392 crlSet.items = signedInfo->rgCrlEncoded;
4393 crlSet.itemSize = sizeof(CRL_BLOB);
4394 crlSet.itemOffset = 0;
4395 crlSet.encode = CRYPT_CopyEncodedBlob;
4396 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
4397 swapped[cSwapped].pvStructInfo = &crlSet;
4398 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4399 items[cItem].pvStructInfo = &swapped[cSwapped];
4400 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4401 cSwapped++;
4402 cItem++;
4404 if (ret && signedInfo->cSignerInfo)
4406 signerSet.cItems = signedInfo->cSignerInfo;
4407 signerSet.items = signedInfo->rgSignerInfo;
4408 signerSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
4409 signerSet.itemOffset = 0;
4410 signerSet.encode = CRYPT_AsnEncodeCMSSignerInfo;
4411 items[cItem].pvStructInfo = &signerSet;
4412 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4413 cItem++;
4415 if (ret)
4416 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
4417 items, cItem, 0, NULL, pvData, pcbData);
4419 return ret;
4422 static BOOL WINAPI CRYPT_AsnEncodeRecipientInfo(DWORD dwCertEncodingType,
4423 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4424 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4426 const CMSG_KEY_TRANS_RECIPIENT_INFO *info = pvStructInfo;
4427 struct AsnEncodeSequenceItem items[] = {
4428 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4429 { &info->RecipientId.u.IssuerSerialNumber,
4430 CRYPT_AsnEncodeIssuerSerialNumber, 0 },
4431 { &info->KeyEncryptionAlgorithm,
4432 CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
4433 { &info->EncryptedKey, CRYPT_AsnEncodeOctets, 0 },
4436 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4437 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4440 static BOOL WINAPI CRYPT_AsnEncodeEncryptedContentInfo(DWORD dwCertEncodingType,
4441 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4442 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4444 const CRYPT_ENCRYPTED_CONTENT_INFO *info = pvStructInfo;
4445 struct AsnEncodeTagSwappedItem swapped = { ASN_CONTEXT | 0,
4446 &info->encryptedContent, CRYPT_AsnEncodeOctets };
4447 struct AsnEncodeSequenceItem items[] = {
4448 { info->contentType, CRYPT_AsnEncodeOid, 0 },
4449 { &info->contentEncryptionAlgorithm,
4450 CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
4451 { &swapped, CRYPT_AsnEncodeSwapTag, 0 },
4454 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4455 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4458 BOOL CRYPT_AsnEncodePKCSEnvelopedData(const CRYPT_ENVELOPED_DATA *envelopedData,
4459 void *pvData, DWORD *pcbData)
4461 struct DERSetDescriptor recipientInfosSet = { envelopedData->cRecipientInfo,
4462 envelopedData->rgRecipientInfo, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO), 0,
4463 CRYPT_AsnEncodeRecipientInfo };
4464 struct AsnEncodeSequenceItem items[] = {
4465 { &envelopedData->version, CRYPT_AsnEncodeInt, 0 },
4466 { &recipientInfosSet, CRYPT_DEREncodeItemsAsSet, 0 },
4467 { &envelopedData->encryptedContentInfo,
4468 CRYPT_AsnEncodeEncryptedContentInfo, 0 },
4471 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
4472 ARRAY_SIZE(items), 0, NULL, pvData, pcbData);
4475 static BOOL WINAPI CRYPT_AsnEncodeCertId(DWORD dwCertEncodingType,
4476 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4477 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4479 BOOL ret;
4481 __TRY
4483 const OCSP_CERT_ID *id = pvStructInfo;
4484 struct AsnEncodeSequenceItem items[] = {
4485 { &id->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
4486 { &id->IssuerNameHash, CRYPT_AsnEncodeOctets, 0 },
4487 { &id->IssuerKeyHash, CRYPT_AsnEncodeOctets, 0 },
4488 { &id->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
4491 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4492 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4494 __EXCEPT_PAGE_FAULT
4496 SetLastError(STATUS_ACCESS_VIOLATION);
4497 ret = FALSE;
4499 __ENDTRY
4500 return ret;
4503 static BOOL WINAPI CRYPT_AsnEncodeOCSPRequestEntry(DWORD dwCertEncodingType,
4504 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4505 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4507 BOOL ret;
4509 __TRY
4511 const OCSP_REQUEST_ENTRY *info = pvStructInfo;
4512 struct AsnEncodeSequenceItem items[] = {
4513 { &info->CertId, CRYPT_AsnEncodeCertId, 0 },
4516 if (info->cExtension)
4518 FIXME("extensions not supported\n");
4519 SetLastError(E_INVALIDARG);
4520 ret = FALSE;
4522 else
4524 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4525 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4528 __EXCEPT_PAGE_FAULT
4530 SetLastError(STATUS_ACCESS_VIOLATION);
4531 ret = FALSE;
4533 __ENDTRY
4534 return ret;
4537 struct ocsp_request_list
4539 DWORD count;
4540 OCSP_REQUEST_ENTRY *entry;
4543 static BOOL WINAPI CRYPT_AsnEncodeOCSPRequestEntries(DWORD dwCertEncodingType,
4544 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4545 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4547 BOOL ret;
4549 __TRY
4551 DWORD bytesNeeded, dataLen, lenBytes, i;
4552 const struct ocsp_request_list *list = pvStructInfo;
4554 ret = TRUE;
4555 for (i = 0, dataLen = 0; ret && i < list->count; i++)
4557 DWORD size;
4558 ret = CRYPT_AsnEncodeOCSPRequestEntry(dwCertEncodingType, lpszStructType, &list->entry[i],
4559 dwFlags, pEncodePara, NULL, &size);
4560 if (ret)
4561 dataLen += size;
4563 if (ret)
4565 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
4566 bytesNeeded = 1 + lenBytes + dataLen;
4567 if (!pbEncoded)
4568 *pcbEncoded = bytesNeeded;
4569 else
4571 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
4572 pbEncoded, pcbEncoded, bytesNeeded)))
4574 BYTE *out;
4576 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
4577 pbEncoded = *(BYTE **)pbEncoded;
4578 out = pbEncoded;
4579 *out++ = ASN_SEQUENCEOF;
4580 CRYPT_EncodeLen(dataLen, out, &lenBytes);
4581 out += lenBytes;
4582 for (i = 0; i < list->count; i++)
4584 DWORD size = dataLen;
4586 ret = CRYPT_AsnEncodeOCSPRequestEntry(dwCertEncodingType, lpszStructType,
4587 &list->entry[i], dwFlags, pEncodePara, out, &size);
4588 out += size;
4589 dataLen -= size;
4592 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
4593 CRYPT_FreeSpace(pEncodePara, pbEncoded);
4598 __EXCEPT_PAGE_FAULT
4600 SetLastError(STATUS_ACCESS_VIOLATION);
4601 ret = FALSE;
4603 __ENDTRY
4604 return ret;
4607 static BOOL WINAPI CRYPT_AsnEncodeOCSPRequest(DWORD dwCertEncodingType,
4608 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4609 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4611 BOOL ret;
4613 __TRY
4615 const OCSP_REQUEST_INFO *info = pvStructInfo;
4617 if (info->dwVersion != OCSP_REQUEST_V1)
4619 FIXME("version %lu not supported\n", info->dwVersion);
4620 SetLastError(E_INVALIDARG);
4621 ret = FALSE;
4623 else
4625 if (info->cExtension)
4627 FIXME("extensions not supported\n");
4628 SetLastError(E_INVALIDARG);
4629 ret = FALSE;
4631 else
4633 struct AsnConstructedItem name;
4634 struct AsnEncodeSequenceItem items[2];
4635 DWORD count = 0;
4637 if (info->pRequestorName)
4639 name.tag = 1;
4640 name.pvStructInfo = info->pRequestorName;
4641 name.encodeFunc = CRYPT_AsnEncodeAltNameEntry;
4642 items[count].pvStructInfo = &name;
4643 items[count].encodeFunc = CRYPT_AsnEncodeConstructed;
4644 count++;
4646 if (info->cRequestEntry)
4648 items[count].pvStructInfo = &info->cRequestEntry;
4649 items[count].encodeFunc = CRYPT_AsnEncodeOCSPRequestEntries;
4650 count++;
4653 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4654 count, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4658 __EXCEPT_PAGE_FAULT
4660 SetLastError(STATUS_ACCESS_VIOLATION);
4661 ret = FALSE;
4663 __ENDTRY
4664 return ret;
4667 static BOOL WINAPI CRYPT_AsnEncodeOCSPSignedRequest(DWORD dwCertEncodingType,
4668 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4669 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4671 BOOL ret;
4673 __TRY
4675 const OCSP_SIGNED_REQUEST_INFO *info = pvStructInfo;
4676 struct AsnEncodeSequenceItem items[] = {
4677 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
4680 if (info->pOptionalSignatureInfo) FIXME("pOptionalSignatureInfo not supported\n");
4682 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4683 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4685 __EXCEPT_PAGE_FAULT
4687 SetLastError(STATUS_ACCESS_VIOLATION);
4688 ret = FALSE;
4690 __ENDTRY
4691 return ret;
4694 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
4695 LPCSTR lpszStructType)
4697 CryptEncodeObjectExFunc encodeFunc = NULL;
4699 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4700 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4702 SetLastError(ERROR_FILE_NOT_FOUND);
4703 return NULL;
4706 if (IS_INTOID(lpszStructType))
4708 switch (LOWORD(lpszStructType))
4710 case LOWORD(X509_CERT):
4711 encodeFunc = CRYPT_AsnEncodeCert;
4712 break;
4713 case LOWORD(X509_CERT_TO_BE_SIGNED):
4714 encodeFunc = CRYPT_AsnEncodeCertInfo;
4715 break;
4716 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
4717 encodeFunc = CRYPT_AsnEncodeCRLInfo;
4718 break;
4719 case LOWORD(X509_EXTENSIONS):
4720 encodeFunc = CRYPT_AsnEncodeExtensions;
4721 break;
4722 case LOWORD(X509_NAME_VALUE):
4723 encodeFunc = CRYPT_AsnEncodeNameValue;
4724 break;
4725 case LOWORD(X509_NAME):
4726 encodeFunc = CRYPT_AsnEncodeName;
4727 break;
4728 case LOWORD(X509_PUBLIC_KEY_INFO):
4729 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
4730 break;
4731 case LOWORD(X509_AUTHORITY_KEY_ID):
4732 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
4733 break;
4734 case LOWORD(X509_ALTERNATE_NAME):
4735 encodeFunc = CRYPT_AsnEncodeAltName;
4736 break;
4737 case LOWORD(X509_BASIC_CONSTRAINTS):
4738 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
4739 break;
4740 case LOWORD(X509_BASIC_CONSTRAINTS2):
4741 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
4742 break;
4743 case LOWORD(X509_CERT_POLICIES):
4744 encodeFunc = CRYPT_AsnEncodeCertPolicies;
4745 break;
4746 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
4747 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
4748 break;
4749 case LOWORD(X509_UNICODE_NAME):
4750 encodeFunc = CRYPT_AsnEncodeUnicodeName;
4751 break;
4752 case LOWORD(PKCS_CONTENT_INFO):
4753 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
4754 break;
4755 case LOWORD(PKCS_ATTRIBUTE):
4756 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
4757 break;
4758 case LOWORD(X509_UNICODE_NAME_VALUE):
4759 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
4760 break;
4761 case LOWORD(X509_OCTET_STRING):
4762 encodeFunc = CRYPT_AsnEncodeOctets;
4763 break;
4764 case LOWORD(X509_BITS):
4765 case LOWORD(X509_KEY_USAGE):
4766 encodeFunc = CRYPT_AsnEncodeBits;
4767 break;
4768 case LOWORD(X509_INTEGER):
4769 encodeFunc = CRYPT_AsnEncodeInt;
4770 break;
4771 case LOWORD(X509_MULTI_BYTE_INTEGER):
4772 encodeFunc = CRYPT_AsnEncodeInteger;
4773 break;
4774 case LOWORD(X509_MULTI_BYTE_UINT):
4775 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
4776 break;
4777 case LOWORD(X509_ENUMERATED):
4778 encodeFunc = CRYPT_AsnEncodeEnumerated;
4779 break;
4780 case LOWORD(X509_CHOICE_OF_TIME):
4781 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
4782 break;
4783 case LOWORD(X509_AUTHORITY_KEY_ID2):
4784 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
4785 break;
4786 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
4787 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
4788 break;
4789 case LOWORD(X509_SEQUENCE_OF_ANY):
4790 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
4791 break;
4792 case LOWORD(PKCS_UTC_TIME):
4793 encodeFunc = CRYPT_AsnEncodeUtcTime;
4794 break;
4795 case LOWORD(X509_CRL_DIST_POINTS):
4796 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
4797 break;
4798 case LOWORD(X509_ENHANCED_KEY_USAGE):
4799 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
4800 break;
4801 case LOWORD(PKCS_CTL):
4802 encodeFunc = CRYPT_AsnEncodeCTL;
4803 break;
4804 case LOWORD(PKCS_SMIME_CAPABILITIES):
4805 encodeFunc = CRYPT_AsnEncodeSMIMECapabilities;
4806 break;
4807 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
4808 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
4809 break;
4810 case LOWORD(PKCS_ATTRIBUTES):
4811 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4812 break;
4813 case LOWORD(X509_ISSUING_DIST_POINT):
4814 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
4815 break;
4816 case LOWORD(X509_NAME_CONSTRAINTS):
4817 encodeFunc = CRYPT_AsnEncodeNameConstraints;
4818 break;
4819 case LOWORD(X509_POLICY_MAPPINGS):
4820 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
4821 break;
4822 case LOWORD(X509_POLICY_CONSTRAINTS):
4823 encodeFunc = CRYPT_AsnEncodeCertPolicyConstraints;
4824 break;
4825 case LOWORD(PKCS7_SIGNER_INFO):
4826 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
4827 break;
4828 case LOWORD(CMS_SIGNER_INFO):
4829 encodeFunc = CRYPT_AsnEncodeCMSSignerInfo;
4830 break;
4831 case LOWORD(CNG_RSA_PUBLIC_KEY_BLOB):
4832 encodeFunc = CRYPT_AsnEncodeRsaPubKey_Bcrypt;
4833 break;
4834 case LOWORD(OCSP_REQUEST):
4835 encodeFunc = CRYPT_AsnEncodeOCSPRequest;
4836 break;
4837 case LOWORD(OCSP_SIGNED_REQUEST):
4838 encodeFunc = CRYPT_AsnEncodeOCSPSignedRequest;
4839 break;
4840 default:
4841 FIXME("Unimplemented encoder for lpszStructType OID %d\n", LOWORD(lpszStructType));
4844 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4845 encodeFunc = CRYPT_AsnEncodeExtensions;
4846 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4847 encodeFunc = CRYPT_AsnEncodeUtcTime;
4848 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
4849 encodeFunc = CRYPT_AsnEncodeUtcTime;
4850 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4851 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
4852 else if (!strcmp(lpszStructType, szOID_LEGACY_POLICY_MAPPINGS))
4853 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
4854 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4855 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
4856 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4857 encodeFunc = CRYPT_AsnEncodeEnumerated;
4858 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4859 encodeFunc = CRYPT_AsnEncodeBits;
4860 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4861 encodeFunc = CRYPT_AsnEncodeOctets;
4862 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4863 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
4864 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4865 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
4866 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4867 encodeFunc = CRYPT_AsnEncodeAltName;
4868 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4869 encodeFunc = CRYPT_AsnEncodeAltName;
4870 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4871 encodeFunc = CRYPT_AsnEncodeAltName;
4872 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4873 encodeFunc = CRYPT_AsnEncodeAltName;
4874 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4875 encodeFunc = CRYPT_AsnEncodeAltName;
4876 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4877 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
4878 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
4879 encodeFunc = CRYPT_AsnEncodeCertPolicies;
4880 else if (!strcmp(lpszStructType, szOID_POLICY_MAPPINGS))
4881 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
4882 else if (!strcmp(lpszStructType, szOID_POLICY_CONSTRAINTS))
4883 encodeFunc = CRYPT_AsnEncodeCertPolicyConstraints;
4884 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4885 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
4886 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4887 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
4888 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
4889 encodeFunc = CRYPT_AsnEncodeNameConstraints;
4890 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
4891 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
4892 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
4893 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
4894 else if (!strcmp(lpszStructType, szOID_CTL))
4895 encodeFunc = CRYPT_AsnEncodeCTL;
4896 else
4897 FIXME("Unsupported encoder for lpszStructType %s\n", lpszStructType);
4898 return encodeFunc;
4901 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType,
4902 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4904 static HCRYPTOIDFUNCSET set = NULL;
4905 CryptEncodeObjectFunc encodeFunc = NULL;
4907 if (!set)
4908 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
4909 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4910 (void **)&encodeFunc, hFunc);
4911 return encodeFunc;
4914 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType,
4915 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4917 static HCRYPTOIDFUNCSET set = NULL;
4918 CryptEncodeObjectExFunc encodeFunc = NULL;
4920 if (!set)
4921 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
4922 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4923 (void **)&encodeFunc, hFunc);
4924 return encodeFunc;
4927 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4928 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
4930 BOOL ret = FALSE;
4931 HCRYPTOIDFUNCADDR hFunc = NULL;
4932 CryptEncodeObjectFunc pCryptEncodeObject = NULL;
4933 CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL;
4935 TRACE_(crypt)("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType,
4936 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
4937 pcbEncoded);
4939 if (!pbEncoded && !pcbEncoded)
4941 SetLastError(ERROR_INVALID_PARAMETER);
4942 return FALSE;
4945 if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType,
4946 lpszStructType)))
4948 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4949 debugstr_a(lpszStructType));
4950 pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType,
4951 lpszStructType, &hFunc);
4952 if (!pCryptEncodeObject)
4953 pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType,
4954 lpszStructType, &hFunc);
4956 if (pCryptEncodeObject)
4957 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4958 pvStructInfo, pbEncoded, pcbEncoded);
4959 else if (pCryptEncodeObjectEx)
4960 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
4961 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
4962 if (hFunc)
4963 CryptFreeOIDFunctionAddress(hFunc, 0);
4964 TRACE_(crypt)("returning %d\n", ret);
4965 return ret;
4968 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4969 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
4970 void *pvEncoded, DWORD *pcbEncoded)
4972 BOOL ret = FALSE;
4973 HCRYPTOIDFUNCADDR hFunc = NULL;
4974 CryptEncodeObjectExFunc encodeFunc = NULL;
4976 TRACE_(crypt)("(0x%08lx, %s, %p, 0x%08lx, %p, %p, %p)\n", dwCertEncodingType,
4977 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
4978 pvEncoded, pcbEncoded);
4980 if (!pvEncoded && !pcbEncoded)
4982 SetLastError(ERROR_INVALID_PARAMETER);
4983 return FALSE;
4986 SetLastError(NOERROR);
4987 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
4988 if (!pvEncoded) {
4989 SetLastError(ERROR_INVALID_PARAMETER);
4990 return FALSE;
4992 *(BYTE **)pvEncoded = NULL;
4994 encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType);
4995 if (!encodeFunc)
4997 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4998 debugstr_a(lpszStructType));
4999 encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType,
5000 &hFunc);
5002 if (encodeFunc)
5003 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
5004 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
5005 else
5007 CryptEncodeObjectFunc pCryptEncodeObject =
5008 CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
5010 if (pCryptEncodeObject)
5012 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
5014 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
5015 pvStructInfo, NULL, pcbEncoded);
5016 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
5017 pvEncoded, pcbEncoded, *pcbEncoded)))
5018 ret = pCryptEncodeObject(dwCertEncodingType,
5019 lpszStructType, pvStructInfo, *(BYTE **)pvEncoded,
5020 pcbEncoded);
5022 else
5023 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
5024 pvStructInfo, pvEncoded, pcbEncoded);
5027 if (hFunc)
5028 CryptFreeOIDFunctionAddress(hFunc, 0);
5029 TRACE_(crypt)("returning %d\n", ret);
5030 return ret;
5033 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
5034 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
5036 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
5037 NULL, 0, NULL, pInfo, pcbInfo);
5040 typedef BOOL (WINAPI *EncodePublicKeyAndParametersFunc)(DWORD dwCertEncodingType,
5041 LPSTR pszPublicKeyObjId, BYTE *pbPubKey, DWORD cbPubKey, DWORD dwFlags, void *pvAuxInfo,
5042 BYTE **ppPublicKey, DWORD *pcbPublicKey, BYTE **ppbParams, DWORD *pcbParams);
5044 static BOOL WINAPI CRYPT_ExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
5045 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
5046 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
5048 BOOL ret;
5049 HCRYPTKEY key;
5050 static CHAR rsa_oid[] = szOID_RSA_RSA;
5052 TRACE_(crypt)("(%08Ix, %ld, %08lx, %s, %08lx, %p, %p, %ld)\n", hCryptProv,
5053 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
5054 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
5056 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
5058 DWORD keySize = 0;
5060 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
5061 if (ret)
5063 PUBLICKEYSTRUC *pubKey = CryptMemAlloc(keySize);
5065 if (pubKey)
5067 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, (BYTE *)pubKey, &keySize);
5068 if (ret)
5070 DWORD encodedLen;
5072 if (!pszPublicKeyObjId)
5074 static HCRYPTOIDFUNCSET set;
5075 EncodePublicKeyAndParametersFunc encodeFunc = NULL;
5076 HCRYPTOIDFUNCADDR hFunc = NULL;
5078 pszPublicKeyObjId = (LPSTR)CertAlgIdToOID(pubKey->aiKeyAlg);
5079 TRACE("public key algid %#x (%s)\n", pubKey->aiKeyAlg, debugstr_a(pszPublicKeyObjId));
5081 if (!set) /* FIXME: there is no a public macro */
5082 set = CryptInitOIDFunctionSet("CryptDllEncodePublicKeyAndParameters", 0);
5084 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId, 0, (void **)&encodeFunc, &hFunc);
5085 if (encodeFunc)
5087 BYTE *key_data = NULL;
5088 DWORD key_size = 0;
5089 BYTE *params = NULL;
5090 DWORD params_size = 0;
5092 ret = encodeFunc(dwCertEncodingType, pszPublicKeyObjId, (BYTE *)pubKey, keySize,
5093 dwFlags, pvAuxInfo, &key_data, &key_size, &params, &params_size);
5094 if (ret)
5096 DWORD oid_size = strlen(pszPublicKeyObjId) + 1;
5097 DWORD size_needed = sizeof(*pInfo) + oid_size + key_size + params_size;
5099 if (!pInfo)
5100 *pcbInfo = size_needed;
5101 else if (*pcbInfo < size_needed)
5103 *pcbInfo = size_needed;
5104 SetLastError(ERROR_MORE_DATA);
5105 ret = FALSE;
5107 else
5109 *pcbInfo = size_needed;
5110 pInfo->Algorithm.pszObjId = (char *)(pInfo + 1);
5111 lstrcpyA(pInfo->Algorithm.pszObjId, pszPublicKeyObjId);
5112 if (params)
5114 pInfo->Algorithm.Parameters.cbData = params_size;
5115 pInfo->Algorithm.Parameters.pbData = (BYTE *)pInfo->Algorithm.pszObjId + oid_size;
5116 memcpy(pInfo->Algorithm.Parameters.pbData, params, params_size);
5118 else
5120 pInfo->Algorithm.Parameters.cbData = 0;
5121 pInfo->Algorithm.Parameters.pbData = NULL;
5123 pInfo->PublicKey.pbData = (BYTE *)pInfo->Algorithm.pszObjId + oid_size + params_size;
5124 pInfo->PublicKey.cbData = key_size;
5125 memcpy(pInfo->PublicKey.pbData, key_data, key_size);
5126 pInfo->PublicKey.cUnusedBits = 0;
5129 CryptMemFree(key_data);
5130 CryptMemFree(params);
5133 CryptMemFree(pubKey);
5134 CryptFreeOIDFunctionAddress(hFunc, 0);
5135 return ret;
5138 /* fallback to RSA */
5139 pszPublicKeyObjId = rsa_oid;
5142 encodedLen = 0;
5143 ret = CryptEncodeObject(dwCertEncodingType,
5144 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
5145 if (ret)
5147 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
5148 strlen(pszPublicKeyObjId) + 1 + encodedLen;
5150 if (!pInfo)
5151 *pcbInfo = sizeNeeded;
5152 else if (*pcbInfo < sizeNeeded)
5154 SetLastError(ERROR_MORE_DATA);
5155 *pcbInfo = sizeNeeded;
5156 ret = FALSE;
5158 else
5160 *pcbInfo = sizeNeeded;
5161 pInfo->Algorithm.pszObjId = (char *)pInfo +
5162 sizeof(CERT_PUBLIC_KEY_INFO);
5163 lstrcpyA(pInfo->Algorithm.pszObjId,
5164 pszPublicKeyObjId);
5165 pInfo->Algorithm.Parameters.cbData = 0;
5166 pInfo->Algorithm.Parameters.pbData = NULL;
5167 pInfo->PublicKey.pbData =
5168 (BYTE *)pInfo->Algorithm.pszObjId
5169 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
5170 pInfo->PublicKey.cbData = encodedLen;
5171 pInfo->PublicKey.cUnusedBits = 0;
5172 ret = CryptEncodeObject(dwCertEncodingType,
5173 RSA_CSP_PUBLICKEYBLOB, pubKey,
5174 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
5178 CryptMemFree(pubKey);
5180 else
5181 ret = FALSE;
5183 CryptDestroyKey(key);
5185 return ret;
5188 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
5189 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
5190 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
5192 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
5193 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
5194 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
5196 static HCRYPTOIDFUNCSET set = NULL;
5197 BOOL ret;
5198 ExportPublicKeyInfoExFunc exportFunc = NULL;
5199 HCRYPTOIDFUNCADDR hFunc = NULL;
5201 TRACE_(crypt)("(%08Ix, %ld, %08lx, %s, %08lx, %p, %p, %ld)\n", hCryptProv,
5202 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
5203 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
5205 if (!hCryptProv)
5207 SetLastError(ERROR_INVALID_PARAMETER);
5208 return FALSE;
5211 if (pszPublicKeyObjId)
5213 if (!set)
5214 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
5216 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
5217 0, (void **)&exportFunc, &hFunc);
5219 if (!exportFunc)
5220 exportFunc = CRYPT_ExportPublicKeyInfoEx;
5221 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
5222 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
5223 if (hFunc)
5224 CryptFreeOIDFunctionAddress(hFunc, 0);
5225 return ret;
5228 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
5229 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
5231 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
5232 0, 0, NULL, phKey);
5235 typedef BOOL (WINAPI *ConvertPublicKeyInfoFunc)(DWORD dwCertEncodingType,
5236 PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg, DWORD dwFlags,
5237 BYTE **ppbData, DWORD *dwDataLen);
5239 static BOOL WINAPI CRYPT_ImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
5240 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
5241 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
5243 static HCRYPTOIDFUNCSET set = NULL;
5244 ConvertPublicKeyInfoFunc convertFunc = NULL;
5245 HCRYPTOIDFUNCADDR hFunc = NULL;
5246 BOOL ret;
5247 DWORD pubKeySize;
5248 LPBYTE pubKey;
5250 TRACE_(crypt)("(%08Ix, %08lx, %p, %08x, %08lx, %p, %p)\n", hCryptProv,
5251 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
5253 if (!set)
5254 set = CryptInitOIDFunctionSet(CRYPT_OID_CONVERT_PUBLIC_KEY_INFO_FUNC, 0);
5255 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pInfo->Algorithm.pszObjId,
5256 0, (void **)&convertFunc, &hFunc);
5257 if (convertFunc)
5259 pubKey = NULL;
5260 pubKeySize = 0;
5261 ret = convertFunc(dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, &pubKey, &pubKeySize);
5262 if (ret)
5264 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0, phKey);
5265 CryptMemFree(pubKey);
5268 CryptFreeOIDFunctionAddress(hFunc, 0);
5269 return ret;
5272 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
5273 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
5274 if (ret)
5276 pubKey = CryptMemAlloc(pubKeySize);
5278 if (pubKey)
5280 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
5281 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
5282 &pubKeySize);
5283 if (ret)
5285 if(aiKeyAlg)
5286 ((BLOBHEADER*)pubKey)->aiKeyAlg = aiKeyAlg;
5287 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
5288 phKey);
5290 CryptMemFree(pubKey);
5292 else
5293 ret = FALSE;
5295 return ret;
5298 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
5299 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
5300 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
5302 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
5303 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
5304 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
5306 static HCRYPTOIDFUNCSET set = NULL;
5307 BOOL ret;
5308 ImportPublicKeyInfoExFunc importFunc = NULL;
5309 HCRYPTOIDFUNCADDR hFunc = NULL;
5311 TRACE_(crypt)("(%08Ix, %08lx, %p, %08x, %08lx, %p, %p)\n", hCryptProv,
5312 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
5314 if (!set)
5315 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
5316 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
5317 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
5318 if (!importFunc)
5319 importFunc = CRYPT_ImportPublicKeyInfoEx;
5320 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
5321 pvAuxInfo, phKey);
5322 if (hFunc)
5323 CryptFreeOIDFunctionAddress(hFunc, 0);
5324 return ret;
5327 BOOL WINAPI CryptImportPublicKeyInfoEx2(DWORD dwCertEncodingType,
5328 PCERT_PUBLIC_KEY_INFO pInfo, DWORD dwFlags, void *pvAuxInfo,
5329 BCRYPT_KEY_HANDLE *phKey)
5331 TRACE_(crypt)("(%ld, %p, %08lx, %p, %p)\n", dwCertEncodingType, pInfo,
5332 dwFlags, pvAuxInfo, phKey);
5334 if (dwFlags)
5335 FIXME("flags %#lx ignored\n", dwFlags);
5337 return CNG_ImportPubKey(pInfo, phKey);