cmd: DIR command outputs free space for the path.
[wine.git] / dlls / crypt32 / encode.c
blob9e362b8db21692653bb892d489253f19980e6075
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 #include "windef.h"
39 #include "winbase.h"
40 #include "wincrypt.h"
41 #include "snmp.h"
42 #include "wine/debug.h"
43 #include "wine/exception.h"
44 #include "crypt32_private.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
47 WINE_DECLARE_DEBUG_CHANNEL(crypt);
49 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
50 BYTE *, DWORD *);
52 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
53 * The dwCertEncodingType and lpszStructType are ignored by the built-in
54 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
55 * since it must call functions in external DLLs that follow these signatures.
57 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
58 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
59 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
60 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
61 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
62 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
63 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
64 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
65 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
66 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
67 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
68 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
69 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
70 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
71 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
72 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
73 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
74 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
75 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
76 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
77 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
78 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
79 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
80 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
81 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
82 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
83 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
84 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
85 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
86 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
87 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
88 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
89 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
90 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
91 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
92 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
93 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
94 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
95 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
97 BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara,
98 BYTE *pbEncoded, DWORD *pcbEncoded, DWORD bytesNeeded)
100 BOOL ret = TRUE;
102 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
104 if (pEncodePara && pEncodePara->pfnAlloc)
105 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
106 else
107 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
108 if (!*(BYTE **)pbEncoded)
109 ret = FALSE;
110 else
111 *pcbEncoded = bytesNeeded;
113 else if (bytesNeeded > *pcbEncoded)
115 *pcbEncoded = bytesNeeded;
116 SetLastError(ERROR_MORE_DATA);
117 ret = FALSE;
119 else
120 *pcbEncoded = bytesNeeded;
121 return ret;
124 static void CRYPT_FreeSpace(const CRYPT_ENCODE_PARA *pEncodePara, LPVOID pv)
126 if (pEncodePara && pEncodePara->pfnFree)
127 pEncodePara->pfnFree(pv);
128 else
129 LocalFree(pv);
132 BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
134 DWORD bytesNeeded, significantBytes = 0;
136 if (len <= 0x7f)
137 bytesNeeded = 1;
138 else
140 DWORD temp;
142 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
143 temp <<= 8, significantBytes--)
145 bytesNeeded = significantBytes + 1;
147 if (!pbEncoded)
149 *pcbEncoded = bytesNeeded;
150 return TRUE;
152 if (*pcbEncoded < bytesNeeded)
154 SetLastError(ERROR_MORE_DATA);
155 return FALSE;
157 if (len <= 0x7f)
158 *pbEncoded = (BYTE)len;
159 else
161 DWORD i;
163 *pbEncoded++ = significantBytes | 0x80;
164 for (i = 0; i < significantBytes; i++)
166 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
167 len >>= 8;
170 *pcbEncoded = bytesNeeded;
171 return TRUE;
174 BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
175 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
176 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
178 BOOL ret;
179 DWORD i, dataLen = 0;
181 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", items, cItem, dwFlags, pEncodePara,
182 pbEncoded, pbEncoded ? *pcbEncoded : 0);
183 for (i = 0, ret = TRUE; ret && i < cItem; i++)
185 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
186 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
187 NULL, &items[i].size);
188 /* Some functions propagate their errors through the size */
189 if (!ret)
190 *pcbEncoded = items[i].size;
191 dataLen += items[i].size;
193 if (ret)
195 DWORD lenBytes, bytesNeeded;
197 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
198 bytesNeeded = 1 + lenBytes + dataLen;
199 if (!pbEncoded)
200 *pcbEncoded = bytesNeeded;
201 else
203 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
204 pcbEncoded, bytesNeeded)))
206 BYTE *out;
208 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
209 pbEncoded = *(BYTE **)pbEncoded;
210 out = pbEncoded;
211 *out++ = ASN_SEQUENCE;
212 CRYPT_EncodeLen(dataLen, out, &lenBytes);
213 out += lenBytes;
214 for (i = 0; ret && i < cItem; i++)
216 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
217 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
218 NULL, out, &items[i].size);
219 /* Some functions propagate their errors through the size */
220 if (!ret)
221 *pcbEncoded = items[i].size;
222 out += items[i].size;
224 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
225 CRYPT_FreeSpace(pEncodePara, pbEncoded);
229 TRACE("returning %d (%08lx)\n", ret, GetLastError());
230 return ret;
233 BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
234 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
235 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
237 BOOL ret;
238 const struct AsnConstructedItem *item = pvStructInfo;
239 DWORD len;
241 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
242 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
244 DWORD dataLen, bytesNeeded;
246 CRYPT_EncodeLen(len, NULL, &dataLen);
247 bytesNeeded = 1 + dataLen + len;
248 if (!pbEncoded)
249 *pcbEncoded = bytesNeeded;
250 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
251 pbEncoded, pcbEncoded, bytesNeeded)))
253 BYTE *out;
255 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
256 pbEncoded = *(BYTE **)pbEncoded;
257 out = pbEncoded;
258 *out++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
259 CRYPT_EncodeLen(len, out, &dataLen);
260 out += dataLen;
261 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
262 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
263 out, &len);
264 if (!ret)
266 /* Some functions propagate their errors through the size */
267 *pcbEncoded = len;
268 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
269 CRYPT_FreeSpace(pEncodePara, pbEncoded);
273 else
275 /* Some functions propagate their errors through the size */
276 *pcbEncoded = len;
278 return ret;
281 struct AsnEncodeTagSwappedItem
283 BYTE tag;
284 const void *pvStructInfo;
285 CryptEncodeObjectExFunc encodeFunc;
288 /* Sort of a wacky hack, it encodes something using the struct
289 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
290 * given in the struct AsnEncodeTagSwappedItem.
292 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
293 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
294 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
296 BOOL ret;
297 const struct AsnEncodeTagSwappedItem *item = pvStructInfo;
299 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
300 item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
301 if (ret && pbEncoded)
302 *pbEncoded = item->tag;
303 return ret;
306 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
307 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
308 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
310 const DWORD *ver = pvStructInfo;
311 BOOL ret;
313 /* CERT_V1 is not encoded */
314 if (*ver == CERT_V1)
316 *pcbEncoded = 0;
317 ret = TRUE;
319 else
321 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
323 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
324 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
326 return ret;
329 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
330 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
331 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
333 const CRYPT_DER_BLOB *blob = pvStructInfo;
334 BOOL ret;
336 if (!pbEncoded)
338 *pcbEncoded = blob->cbData;
339 ret = TRUE;
341 else
343 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
344 pcbEncoded, blob->cbData)))
346 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
347 pbEncoded = *(BYTE **)pbEncoded;
348 if (blob->cbData)
349 memcpy(pbEncoded, blob->pbData, blob->cbData);
350 *pcbEncoded = blob->cbData;
353 return ret;
356 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
357 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
358 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
360 BOOL ret;
361 /* This has two filetimes in a row, a NotBefore and a NotAfter */
362 const FILETIME *timePtr = pvStructInfo;
363 struct AsnEncodeSequenceItem items[] = {
364 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
365 { timePtr + 1, CRYPT_AsnEncodeChoiceOfTime, 0 },
368 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
369 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
370 pcbEncoded);
371 return ret;
374 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
375 * if they are empty.
377 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
378 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
379 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
380 DWORD *pcbEncoded)
382 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
383 static const BYTE asn1Null[] = { ASN_NULL, 0 };
384 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
385 (LPBYTE)asn1Null };
386 BOOL ret;
387 struct AsnEncodeSequenceItem items[2] = {
388 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
389 { NULL, CRYPT_CopyEncodedBlob, 0 },
392 if (algo->Parameters.cbData)
393 items[1].pvStructInfo = &algo->Parameters;
394 else
395 items[1].pvStructInfo = &nullBlob;
396 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
397 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
398 pcbEncoded);
399 return ret;
402 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType,
403 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
404 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
406 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
407 BOOL ret;
408 struct AsnEncodeSequenceItem items[] = {
409 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
410 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
413 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
414 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
415 pcbEncoded);
416 return ret;
419 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
420 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
421 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
423 BOOL ret;
425 __TRY
427 const CERT_PUBLIC_KEY_INFO *info = pvStructInfo;
428 struct AsnEncodeSequenceItem items[] = {
429 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
430 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
433 TRACE("Encoding public key with OID %s\n",
434 debugstr_a(info->Algorithm.pszObjId));
435 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
436 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
437 pcbEncoded);
439 __EXCEPT_PAGE_FAULT
441 SetLastError(STATUS_ACCESS_VIOLATION);
442 ret = FALSE;
444 __ENDTRY
445 return ret;
448 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
449 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
450 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
452 BOOL ret;
454 __TRY
456 const CERT_SIGNED_CONTENT_INFO *info = pvStructInfo;
457 struct AsnEncodeSequenceItem items[] = {
458 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
459 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
460 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
463 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
464 items[2].encodeFunc = CRYPT_AsnEncodeBits;
465 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
466 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
467 pcbEncoded);
469 __EXCEPT_PAGE_FAULT
471 SetLastError(STATUS_ACCESS_VIOLATION);
472 ret = FALSE;
474 __ENDTRY
475 return ret;
478 BOOL WINAPI CRYPT_AsnEncodePubKeyInfoNoNull(DWORD dwCertEncodingType,
479 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
480 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
482 BOOL ret;
483 const CERT_PUBLIC_KEY_INFO *info = pvStructInfo;
484 struct AsnEncodeSequenceItem items[] = {
485 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
486 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
489 TRACE("Encoding public key with OID %s\n",
490 debugstr_a(info->Algorithm.pszObjId));
491 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
492 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
493 pcbEncoded);
494 return ret;
497 /* Like in Windows, this blithely ignores the validity of the passed-in
498 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
499 * decode properly, see CRYPT_AsnDecodeCertInfo.
501 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
502 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
503 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
505 BOOL ret;
507 __TRY
509 const CERT_INFO *info = pvStructInfo;
510 struct AsnEncodeSequenceItem items[10] = {
511 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
512 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
513 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
514 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
515 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
516 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
517 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfoNoNull, 0 },
518 { 0 }
520 struct AsnConstructedItem constructed = { 0 };
521 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
522 DWORD cItem = 7, cSwapped = 0;
524 if (info->IssuerUniqueId.cbData)
526 swapped[cSwapped].tag = ASN_CONTEXT | 1;
527 swapped[cSwapped].pvStructInfo = &info->IssuerUniqueId;
528 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
529 items[cItem].pvStructInfo = &swapped[cSwapped];
530 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
531 cSwapped++;
532 cItem++;
534 if (info->SubjectUniqueId.cbData)
536 swapped[cSwapped].tag = ASN_CONTEXT | 2;
537 swapped[cSwapped].pvStructInfo = &info->SubjectUniqueId;
538 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
539 items[cItem].pvStructInfo = &swapped[cSwapped];
540 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
541 cSwapped++;
542 cItem++;
544 if (info->cExtension)
546 constructed.tag = 3;
547 constructed.pvStructInfo = &info->cExtension;
548 constructed.encodeFunc = CRYPT_AsnEncodeExtensions;
549 items[cItem].pvStructInfo = &constructed;
550 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
551 cItem++;
554 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
555 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
557 __EXCEPT_PAGE_FAULT
559 SetLastError(STATUS_ACCESS_VIOLATION);
560 ret = FALSE;
562 __ENDTRY
563 return ret;
566 static BOOL CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
567 BYTE *pbEncoded, DWORD *pcbEncoded)
569 struct AsnEncodeSequenceItem items[3] = {
570 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
571 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
572 { 0 }
574 DWORD cItem = 2;
575 BOOL ret;
577 TRACE("%p, %p, %ld\n", entry, pbEncoded, pbEncoded ? *pcbEncoded : 0);
579 if (entry->cExtension)
581 items[cItem].pvStructInfo = &entry->cExtension;
582 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
583 cItem++;
586 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
587 pbEncoded, pcbEncoded);
589 TRACE("returning %d (%08lx)\n", ret, GetLastError());
590 return ret;
593 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
594 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
595 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
597 DWORD bytesNeeded, dataLen, lenBytes, i;
598 const CRL_INFO *info = pvStructInfo;
599 const CRL_ENTRY *rgCRLEntry = info->rgCRLEntry;
600 BOOL ret = TRUE;
602 for (i = 0, dataLen = 0; ret && i < info->cCRLEntry; i++)
604 DWORD size;
606 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
607 if (ret)
608 dataLen += size;
610 if (ret)
612 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
613 bytesNeeded = 1 + lenBytes + dataLen;
614 if (!pbEncoded)
615 *pcbEncoded = bytesNeeded;
616 else
618 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
619 pcbEncoded, bytesNeeded)))
621 BYTE *out;
623 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
624 pbEncoded = *(BYTE **)pbEncoded;
625 out = pbEncoded;
626 *out++ = ASN_SEQUENCEOF;
627 CRYPT_EncodeLen(dataLen, out, &lenBytes);
628 out += lenBytes;
629 for (i = 0; i < info->cCRLEntry; i++)
631 DWORD size = dataLen;
633 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], out, &size);
634 out += size;
635 dataLen -= size;
637 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
638 CRYPT_FreeSpace(pEncodePara, pbEncoded);
642 return ret;
645 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
646 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
647 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
649 const DWORD *ver = pvStructInfo;
650 BOOL ret;
652 /* CRL_V1 is not encoded */
653 if (*ver == CRL_V1)
655 *pcbEncoded = 0;
656 ret = TRUE;
658 else
659 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
660 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
661 return ret;
664 /* Like in Windows, this blithely ignores the validity of the passed-in
665 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
666 * decode properly, see CRYPT_AsnDecodeCRLInfo.
668 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
669 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
670 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
672 BOOL ret;
674 __TRY
676 const CRL_INFO *info = pvStructInfo;
677 struct AsnEncodeSequenceItem items[7] = {
678 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
679 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
680 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
681 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
682 { 0 }
684 struct AsnConstructedItem constructed[1] = { { 0 } };
685 DWORD cItem = 4, cConstructed = 0;
687 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
689 items[cItem].pvStructInfo = &info->NextUpdate;
690 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
691 cItem++;
693 if (info->cCRLEntry)
695 items[cItem].pvStructInfo = info;
696 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
697 cItem++;
699 if (info->cExtension)
701 constructed[cConstructed].tag = 0;
702 constructed[cConstructed].pvStructInfo = &info->cExtension;
703 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
704 items[cItem].pvStructInfo = &constructed[cConstructed];
705 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
706 cConstructed++;
707 cItem++;
710 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
711 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
713 __EXCEPT_PAGE_FAULT
715 SetLastError(STATUS_ACCESS_VIOLATION);
716 ret = FALSE;
718 __ENDTRY
719 return ret;
722 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
723 DWORD *pcbEncoded)
725 BOOL ret;
726 struct AsnEncodeSequenceItem items[3] = {
727 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
728 { NULL, NULL, 0 },
729 { NULL, NULL, 0 },
731 DWORD cItem = 1;
733 TRACE("%p, %p, %ld\n", ext, pbEncoded, pbEncoded ? *pcbEncoded : 0);
735 if (ext->fCritical)
737 items[cItem].pvStructInfo = &ext->fCritical;
738 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
739 cItem++;
741 items[cItem].pvStructInfo = &ext->Value;
742 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
743 cItem++;
745 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
746 pbEncoded, pcbEncoded);
747 TRACE("returning %d (%08lx)\n", ret, GetLastError());
748 return ret;
751 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
752 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
753 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
755 BOOL ret;
757 __TRY
759 DWORD bytesNeeded, dataLen, lenBytes, i;
760 const CERT_EXTENSIONS *exts = pvStructInfo;
762 ret = TRUE;
763 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
765 DWORD size;
767 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
768 if (ret)
769 dataLen += size;
771 if (ret)
773 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
774 bytesNeeded = 1 + lenBytes + dataLen;
775 if (!pbEncoded)
776 *pcbEncoded = bytesNeeded;
777 else
779 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
780 pbEncoded, pcbEncoded, bytesNeeded)))
782 BYTE *out;
784 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
785 pbEncoded = *(BYTE **)pbEncoded;
786 out = pbEncoded;
787 *out++ = ASN_SEQUENCEOF;
788 CRYPT_EncodeLen(dataLen, out, &lenBytes);
789 out += lenBytes;
790 for (i = 0; i < exts->cExtension; i++)
792 DWORD size = dataLen;
794 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
795 out, &size);
796 out += size;
797 dataLen -= size;
799 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
800 CRYPT_FreeSpace(pEncodePara, pbEncoded);
805 __EXCEPT_PAGE_FAULT
807 SetLastError(STATUS_ACCESS_VIOLATION);
808 ret = FALSE;
810 __ENDTRY
811 return ret;
814 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
815 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
816 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
818 LPCSTR pszObjId = pvStructInfo;
819 DWORD bytesNeeded = 0, lenBytes;
820 BOOL ret = TRUE;
821 int firstPos = 0;
822 BYTE firstByte = 0;
824 TRACE("%s\n", debugstr_a(pszObjId));
826 if (pszObjId)
828 const char *ptr;
829 int val1, val2;
831 if (sscanf(pszObjId, "%d.%d%n", &val1, &val2, &firstPos) != 2)
833 SetLastError(CRYPT_E_ASN1_ERROR);
834 return FALSE;
836 bytesNeeded++;
837 firstByte = val1 * 40 + val2;
838 ptr = pszObjId + firstPos;
839 if (*ptr == '.')
841 ptr++;
842 firstPos++;
844 while (ret && *ptr)
846 int pos;
848 /* note I assume each component is at most 32-bits long in base 2 */
849 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
851 if (val1 >= 0x10000000)
852 bytesNeeded += 5;
853 else if (val1 >= 0x200000)
854 bytesNeeded += 4;
855 else if (val1 >= 0x4000)
856 bytesNeeded += 3;
857 else if (val1 >= 0x80)
858 bytesNeeded += 2;
859 else
860 bytesNeeded += 1;
861 ptr += pos;
862 if (*ptr == '.')
863 ptr++;
865 else
867 SetLastError(CRYPT_E_ASN1_ERROR);
868 return FALSE;
871 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
873 else
874 lenBytes = 1;
875 bytesNeeded += 1 + lenBytes;
876 if (pbEncoded)
878 if (*pcbEncoded < bytesNeeded)
880 SetLastError(ERROR_MORE_DATA);
881 ret = FALSE;
883 else
885 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
886 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
887 pbEncoded += lenBytes;
888 if (pszObjId)
890 const char *ptr;
891 int val, pos;
893 *pbEncoded++ = firstByte;
894 ptr = pszObjId + firstPos;
895 while (ret && *ptr)
897 sscanf(ptr, "%d%n", &val, &pos);
899 unsigned char outBytes[5];
900 int numBytes, i;
902 if (val >= 0x10000000)
903 numBytes = 5;
904 else if (val >= 0x200000)
905 numBytes = 4;
906 else if (val >= 0x4000)
907 numBytes = 3;
908 else if (val >= 0x80)
909 numBytes = 2;
910 else
911 numBytes = 1;
912 for (i = numBytes; i > 0; i--)
914 outBytes[i - 1] = val & 0x7f;
915 val >>= 7;
917 for (i = 0; i < numBytes - 1; i++)
918 *pbEncoded++ = outBytes[i] | 0x80;
919 *pbEncoded++ = outBytes[i];
920 ptr += pos;
921 if (*ptr == '.')
922 ptr++;
928 *pcbEncoded = bytesNeeded;
929 return ret;
932 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
933 BYTE tag, DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
934 DWORD *pcbEncoded)
936 BOOL ret = TRUE;
937 LPCSTR str = (LPCSTR)value->Value.pbData;
938 DWORD bytesNeeded, lenBytes, encodedLen;
940 encodedLen = value->Value.cbData ? value->Value.cbData : strlen(str);
941 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
942 bytesNeeded = 1 + lenBytes + encodedLen;
943 if (!pbEncoded)
944 *pcbEncoded = bytesNeeded;
945 else
947 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
948 pbEncoded, pcbEncoded, bytesNeeded)))
950 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
951 pbEncoded = *(BYTE **)pbEncoded;
952 *pbEncoded++ = tag;
953 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
954 pbEncoded += lenBytes;
955 memcpy(pbEncoded, str, encodedLen);
958 return ret;
961 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
962 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
963 DWORD *pcbEncoded)
965 BOOL ret = TRUE;
966 LPCWSTR str = (LPCWSTR)value->Value.pbData;
967 DWORD bytesNeeded, lenBytes, strLen;
969 if (value->Value.cbData)
970 strLen = value->Value.cbData / sizeof(WCHAR);
971 else if (value->Value.pbData)
972 strLen = lstrlenW(str);
973 else
974 strLen = 0;
975 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
976 bytesNeeded = 1 + lenBytes + strLen * 2;
977 if (!pbEncoded)
978 *pcbEncoded = bytesNeeded;
979 else
981 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
982 pbEncoded, pcbEncoded, bytesNeeded)))
984 DWORD i;
986 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
987 pbEncoded = *(BYTE **)pbEncoded;
988 *pbEncoded++ = ASN_BMPSTRING;
989 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
990 pbEncoded += lenBytes;
991 for (i = 0; i < strLen; i++)
993 *pbEncoded++ = (str[i] & 0xff00) >> 8;
994 *pbEncoded++ = str[i] & 0x00ff;
998 return ret;
1001 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
1002 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
1003 DWORD *pcbEncoded)
1005 BOOL ret = TRUE;
1006 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1007 DWORD bytesNeeded, lenBytes, encodedLen, strLen;
1009 if (value->Value.cbData)
1010 strLen = value->Value.cbData / sizeof(WCHAR);
1011 else if (str)
1012 strLen = lstrlenW(str);
1013 else
1014 strLen = 0;
1015 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
1016 NULL);
1017 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1018 bytesNeeded = 1 + lenBytes + encodedLen;
1019 if (!pbEncoded)
1020 *pcbEncoded = bytesNeeded;
1021 else
1023 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1024 pbEncoded, pcbEncoded, bytesNeeded)))
1026 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1027 pbEncoded = *(BYTE **)pbEncoded;
1028 *pbEncoded++ = ASN_UTF8STRING;
1029 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1030 pbEncoded += lenBytes;
1031 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
1032 bytesNeeded - lenBytes - 1, NULL, NULL);
1035 return ret;
1038 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
1039 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1040 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1042 BOOL ret = TRUE;
1044 __TRY
1046 const CERT_NAME_VALUE *value = pvStructInfo;
1048 switch (value->dwValueType)
1050 case CERT_RDN_ANY_TYPE:
1051 /* explicitly disallowed */
1052 SetLastError(E_INVALIDARG);
1053 ret = FALSE;
1054 break;
1055 case CERT_RDN_ENCODED_BLOB:
1056 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
1057 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1058 break;
1059 case CERT_RDN_OCTET_STRING:
1060 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1061 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1062 break;
1063 case CERT_RDN_NUMERIC_STRING:
1064 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1065 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1066 break;
1067 case CERT_RDN_PRINTABLE_STRING:
1068 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1069 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1070 break;
1071 case CERT_RDN_TELETEX_STRING:
1072 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1073 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1074 break;
1075 case CERT_RDN_VIDEOTEX_STRING:
1076 ret = CRYPT_AsnEncodeStringCoerce(value,
1077 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1078 break;
1079 case CERT_RDN_IA5_STRING:
1080 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1081 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1082 break;
1083 case CERT_RDN_GRAPHIC_STRING:
1084 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1085 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1086 break;
1087 case CERT_RDN_VISIBLE_STRING:
1088 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1089 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1090 break;
1091 case CERT_RDN_GENERAL_STRING:
1092 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1093 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1094 break;
1095 case CERT_RDN_UNIVERSAL_STRING:
1096 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1097 SetLastError(CRYPT_E_ASN1_CHOICE);
1098 ret = FALSE;
1099 break;
1100 case CERT_RDN_BMP_STRING:
1101 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1102 pbEncoded, pcbEncoded);
1103 break;
1104 case CERT_RDN_UTF8_STRING:
1105 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1106 pbEncoded, pcbEncoded);
1107 break;
1108 default:
1109 SetLastError(CRYPT_E_ASN1_CHOICE);
1110 ret = FALSE;
1113 __EXCEPT_PAGE_FAULT
1115 SetLastError(STATUS_ACCESS_VIOLATION);
1116 ret = FALSE;
1118 __ENDTRY
1119 return ret;
1122 static BOOL CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1123 const CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1124 BYTE *pbEncoded, DWORD *pcbEncoded)
1126 DWORD bytesNeeded = 0, lenBytes, size;
1127 BOOL ret;
1129 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1130 0, NULL, NULL, &size);
1131 if (ret)
1133 bytesNeeded += size;
1134 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1135 * with dwValueType, so "cast" it to get its encoded size
1137 ret = nameValueEncodeFunc(dwCertEncodingType, NULL, &attr->dwValueType,
1138 0, NULL, NULL, &size);
1139 if (ret)
1141 bytesNeeded += size;
1142 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1143 bytesNeeded += 1 + lenBytes;
1144 if (pbEncoded)
1146 if (*pcbEncoded < bytesNeeded)
1148 SetLastError(ERROR_MORE_DATA);
1149 ret = FALSE;
1151 else
1153 *pbEncoded++ = ASN_SEQUENCE;
1154 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1155 &lenBytes);
1156 pbEncoded += lenBytes;
1157 size = bytesNeeded - 1 - lenBytes;
1158 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1159 attr->pszObjId, 0, NULL, pbEncoded, &size);
1160 if (ret)
1162 pbEncoded += size;
1163 size = bytesNeeded - 1 - lenBytes - size;
1164 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1165 &attr->dwValueType, 0, NULL, pbEncoded, &size);
1166 if (!ret)
1167 *pcbEncoded = size;
1171 if (ret)
1172 *pcbEncoded = bytesNeeded;
1174 else
1176 /* Have to propagate index of failing character */
1177 *pcbEncoded = size;
1180 return ret;
1183 static int __cdecl BLOBComp(const void *l, const void *r)
1185 const CRYPT_DER_BLOB *a = l, *b = r;
1186 int ret;
1188 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1189 ret = a->cbData - b->cbData;
1190 return ret;
1193 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1195 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1196 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1197 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1199 const CRYPT_BLOB_ARRAY *set = pvStructInfo;
1200 DWORD bytesNeeded = 0, lenBytes, i;
1201 BOOL ret;
1203 for (i = 0; i < set->cBlob; i++)
1204 bytesNeeded += set->rgBlob[i].cbData;
1205 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1206 bytesNeeded += 1 + lenBytes;
1207 if (!pbEncoded)
1209 *pcbEncoded = bytesNeeded;
1210 ret = TRUE;
1212 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1213 pbEncoded, pcbEncoded, bytesNeeded)))
1215 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1216 pbEncoded = *(BYTE **)pbEncoded;
1217 qsort(set->rgBlob, set->cBlob, sizeof(CRYPT_DER_BLOB), BLOBComp);
1218 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1219 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1220 pbEncoded += lenBytes;
1221 for (i = 0; i < set->cBlob; i++)
1223 memcpy(pbEncoded, set->rgBlob[i].pbData, set->rgBlob[i].cbData);
1224 pbEncoded += set->rgBlob[i].cbData;
1227 return ret;
1230 struct DERSetDescriptor
1232 DWORD cItems;
1233 const void *items;
1234 size_t itemSize;
1235 size_t itemOffset;
1236 CryptEncodeObjectExFunc encode;
1239 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,
1240 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1241 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1243 const struct DERSetDescriptor *desc = pvStructInfo;
1244 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1245 BOOL ret = TRUE;
1246 DWORD i;
1248 if (desc->cItems)
1250 setOf.rgBlob = CryptMemAlloc(desc->cItems * sizeof(CRYPT_DER_BLOB));
1251 if (!setOf.rgBlob)
1252 ret = FALSE;
1253 else
1255 setOf.cBlob = desc->cItems;
1256 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1259 for (i = 0; ret && i < setOf.cBlob; i++)
1261 ret = desc->encode(dwCertEncodingType, lpszStructType,
1262 (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
1263 0, NULL, NULL, &setOf.rgBlob[i].cbData);
1264 if (ret)
1266 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1267 if (!setOf.rgBlob[i].pbData)
1268 ret = FALSE;
1269 else
1270 ret = desc->encode(dwCertEncodingType, lpszStructType,
1271 (const BYTE *)desc->items + i * desc->itemSize +
1272 desc->itemOffset, 0, NULL, setOf.rgBlob[i].pbData,
1273 &setOf.rgBlob[i].cbData);
1275 /* Some functions propagate their errors through the size */
1276 if (!ret)
1277 *pcbEncoded = setOf.rgBlob[i].cbData;
1279 if (ret)
1281 DWORD bytesNeeded = 0, lenBytes;
1283 for (i = 0; i < setOf.cBlob; i++)
1284 bytesNeeded += setOf.rgBlob[i].cbData;
1285 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1286 bytesNeeded += 1 + lenBytes;
1287 if (!pbEncoded)
1288 *pcbEncoded = bytesNeeded;
1289 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1290 pbEncoded, pcbEncoded, bytesNeeded)))
1292 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1293 pbEncoded = *(BYTE **)pbEncoded;
1294 qsort(setOf.rgBlob, setOf.cBlob, sizeof(CRYPT_DER_BLOB),
1295 BLOBComp);
1296 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1297 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1298 pbEncoded += lenBytes;
1299 for (i = 0; i < setOf.cBlob; i++)
1301 memcpy(pbEncoded, setOf.rgBlob[i].pbData,
1302 setOf.rgBlob[i].cbData);
1303 pbEncoded += setOf.rgBlob[i].cbData;
1307 for (i = 0; i < setOf.cBlob; i++)
1308 CryptMemFree(setOf.rgBlob[i].pbData);
1309 CryptMemFree(setOf.rgBlob);
1310 return ret;
1313 static BOOL CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, const CERT_RDN *rdn,
1314 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1315 DWORD *pcbEncoded)
1317 BOOL ret;
1318 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1320 __TRY
1322 DWORD i;
1324 ret = TRUE;
1325 if (rdn->cRDNAttr)
1327 setOf.rgBlob = CryptMemAlloc(rdn->cRDNAttr *
1328 sizeof(CRYPT_DER_BLOB));
1329 if (!setOf.rgBlob)
1330 ret = FALSE;
1331 else
1333 setOf.cBlob = rdn->cRDNAttr;
1334 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1337 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1339 setOf.rgBlob[i].cbData = 0;
1340 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1341 nameValueEncodeFunc, NULL, &setOf.rgBlob[i].cbData);
1342 if (ret)
1344 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1345 if (!setOf.rgBlob[i].pbData)
1346 ret = FALSE;
1347 else
1348 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1349 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1350 setOf.rgBlob[i].pbData, &setOf.rgBlob[i].cbData);
1352 if (!ret)
1354 /* Have to propagate index of failing character */
1355 *pcbEncoded = setOf.rgBlob[i].cbData;
1358 if (ret)
1359 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1360 pbEncoded, pcbEncoded);
1361 for (i = 0; i < setOf.cBlob; i++)
1362 CryptMemFree(setOf.rgBlob[i].pbData);
1364 __EXCEPT_PAGE_FAULT
1366 SetLastError(STATUS_ACCESS_VIOLATION);
1367 ret = FALSE;
1369 __ENDTRY
1370 CryptMemFree(setOf.rgBlob);
1371 return ret;
1374 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1375 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1376 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1378 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1379 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1380 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1381 DWORD *pcbEncoded)
1383 const CERT_NAME_VALUE *value = pvStructInfo;
1384 BOOL ret;
1386 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1387 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1388 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1389 else
1390 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1391 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1392 return ret;
1395 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1396 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1397 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1399 BOOL ret = TRUE;
1401 __TRY
1403 const CERT_NAME_INFO *info = pvStructInfo;
1404 DWORD bytesNeeded = 0, lenBytes, size, i;
1406 TRACE("encoding name with %ld RDNs\n", info->cRDN);
1407 ret = TRUE;
1408 for (i = 0; ret && i < info->cRDN; i++)
1410 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1411 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1412 if (ret)
1413 bytesNeeded += size;
1414 else
1415 *pcbEncoded = size;
1417 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1418 bytesNeeded += 1 + lenBytes;
1419 if (ret)
1421 if (!pbEncoded)
1422 *pcbEncoded = bytesNeeded;
1423 else
1425 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1426 pbEncoded, pcbEncoded, bytesNeeded)))
1428 BYTE *out;
1430 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1431 pbEncoded = *(BYTE **)pbEncoded;
1432 out = pbEncoded;
1433 *out++ = ASN_SEQUENCEOF;
1434 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
1435 out += lenBytes;
1436 for (i = 0; ret && i < info->cRDN; i++)
1438 size = bytesNeeded;
1439 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1440 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1441 out, &size);
1442 if (ret)
1444 out += size;
1445 bytesNeeded -= size;
1447 else
1448 *pcbEncoded = size;
1450 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1451 CRYPT_FreeSpace(pEncodePara, pbEncoded);
1456 __EXCEPT_PAGE_FAULT
1458 SetLastError(STATUS_ACCESS_VIOLATION);
1459 ret = FALSE;
1461 __ENDTRY
1462 return ret;
1465 static BOOL WINAPI CRYPT_AsnEncodeCTLVersion(DWORD dwCertEncodingType,
1466 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1467 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1469 const DWORD *ver = pvStructInfo;
1470 BOOL ret;
1472 /* CTL_V1 is not encoded */
1473 if (*ver == CTL_V1)
1475 *pcbEncoded = 0;
1476 ret = TRUE;
1478 else
1479 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
1480 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1481 return ret;
1484 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
1485 * if they are empty and the OID is not empty (otherwise omits them.)
1487 static BOOL WINAPI CRYPT_AsnEncodeCTLSubjectAlgorithm(
1488 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1489 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1490 DWORD *pcbEncoded)
1492 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
1493 BOOL ret;
1494 struct AsnEncodeSequenceItem items[2] = {
1495 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
1497 DWORD cItem = 1;
1499 if (algo->pszObjId)
1501 static const BYTE asn1Null[] = { ASN_NULL, 0 };
1502 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
1503 (LPBYTE)asn1Null };
1505 if (algo->Parameters.cbData)
1506 items[cItem].pvStructInfo = &algo->Parameters;
1507 else
1508 items[cItem].pvStructInfo = &nullBlob;
1509 items[cItem].encodeFunc = CRYPT_CopyEncodedBlob;
1510 cItem++;
1512 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1513 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1514 return ret;
1517 static BOOL CRYPT_AsnEncodeCTLEntry(const CTL_ENTRY *entry,
1518 BYTE *pbEncoded, DWORD *pcbEncoded)
1520 struct AsnEncodeSequenceItem items[2] = {
1521 { &entry->SubjectIdentifier, CRYPT_AsnEncodeOctets, 0 },
1522 { &entry->cAttribute, CRYPT_AsnEncodePKCSAttributes, 0 },
1524 BOOL ret;
1526 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1527 ARRAY_SIZE(items), 0, NULL, pbEncoded, pcbEncoded);
1528 return ret;
1531 struct CTLEntries
1533 DWORD cEntry;
1534 CTL_ENTRY *rgEntry;
1537 static BOOL WINAPI CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType,
1538 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1539 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1541 BOOL ret;
1542 DWORD bytesNeeded, dataLen, lenBytes, i;
1543 const struct CTLEntries *entries = pvStructInfo;
1545 ret = TRUE;
1546 for (i = 0, dataLen = 0; ret && i < entries->cEntry; i++)
1548 DWORD size;
1550 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i], NULL, &size);
1551 if (ret)
1552 dataLen += size;
1554 if (ret)
1556 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1557 bytesNeeded = 1 + lenBytes + dataLen;
1558 if (!pbEncoded)
1559 *pcbEncoded = bytesNeeded;
1560 else
1562 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1563 pbEncoded, pcbEncoded, bytesNeeded)))
1565 BYTE *out;
1567 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1568 pbEncoded = *(BYTE **)pbEncoded;
1569 out = pbEncoded;
1570 *out++ = ASN_SEQUENCEOF;
1571 CRYPT_EncodeLen(dataLen, out, &lenBytes);
1572 out += lenBytes;
1573 for (i = 0; ret && i < entries->cEntry; i++)
1575 DWORD size = dataLen;
1577 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i],
1578 out, &size);
1579 out += size;
1580 dataLen -= size;
1582 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1583 CRYPT_FreeSpace(pEncodePara, pbEncoded);
1587 return ret;
1590 static BOOL WINAPI CRYPT_AsnEncodeCTL(DWORD dwCertEncodingType,
1591 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1592 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1594 BOOL ret = FALSE;
1596 __TRY
1598 const CTL_INFO *info = pvStructInfo;
1599 struct AsnEncodeSequenceItem items[9] = {
1600 { &info->dwVersion, CRYPT_AsnEncodeCTLVersion, 0 },
1601 { &info->SubjectUsage, CRYPT_AsnEncodeEnhancedKeyUsage, 0 },
1603 struct AsnConstructedItem constructed = { 0 };
1604 DWORD cItem = 2;
1606 if (info->ListIdentifier.cbData)
1608 items[cItem].pvStructInfo = &info->ListIdentifier;
1609 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
1610 cItem++;
1612 if (info->SequenceNumber.cbData)
1614 items[cItem].pvStructInfo = &info->SequenceNumber;
1615 items[cItem].encodeFunc = CRYPT_AsnEncodeInteger;
1616 cItem++;
1618 items[cItem].pvStructInfo = &info->ThisUpdate;
1619 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1620 cItem++;
1621 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
1623 items[cItem].pvStructInfo = &info->NextUpdate;
1624 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1625 cItem++;
1627 items[cItem].pvStructInfo = &info->SubjectAlgorithm;
1628 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLSubjectAlgorithm;
1629 cItem++;
1630 if (info->cCTLEntry)
1632 items[cItem].pvStructInfo = &info->cCTLEntry;
1633 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLEntries;
1634 cItem++;
1636 if (info->cExtension)
1638 constructed.tag = 0;
1639 constructed.pvStructInfo = &info->cExtension;
1640 constructed.encodeFunc = CRYPT_AsnEncodeExtensions;
1641 items[cItem].pvStructInfo = &constructed;
1642 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1643 cItem++;
1645 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1646 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1648 __EXCEPT_PAGE_FAULT
1650 SetLastError(STATUS_ACCESS_VIOLATION);
1652 __ENDTRY
1653 return ret;
1656 static BOOL CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType,
1657 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1658 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1660 BOOL ret = FALSE;
1662 __TRY
1664 const CRYPT_SMIME_CAPABILITY *capability = pvStructInfo;
1666 if (!capability->pszObjId)
1667 SetLastError(E_INVALIDARG);
1668 else
1670 struct AsnEncodeSequenceItem items[] = {
1671 { capability->pszObjId, CRYPT_AsnEncodeOid, 0 },
1672 { &capability->Parameters, CRYPT_CopyEncodedBlob, 0 },
1675 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1676 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
1677 pcbEncoded);
1680 __EXCEPT_PAGE_FAULT
1682 SetLastError(STATUS_ACCESS_VIOLATION);
1684 __ENDTRY
1685 return ret;
1688 static BOOL WINAPI CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType,
1689 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1690 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1692 BOOL ret = FALSE;
1694 __TRY
1696 DWORD bytesNeeded, dataLen, lenBytes, i;
1697 const CRYPT_SMIME_CAPABILITIES *capabilities = pvStructInfo;
1699 ret = TRUE;
1700 for (i = 0, dataLen = 0; ret && i < capabilities->cCapability; i++)
1702 DWORD size;
1704 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType, NULL,
1705 &capabilities->rgCapability[i], 0, NULL, NULL, &size);
1706 if (ret)
1707 dataLen += size;
1709 if (ret)
1711 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1712 bytesNeeded = 1 + lenBytes + dataLen;
1713 if (!pbEncoded)
1714 *pcbEncoded = bytesNeeded;
1715 else
1717 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1718 pbEncoded, pcbEncoded, bytesNeeded)))
1720 BYTE *out;
1722 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1723 pbEncoded = *(BYTE **)pbEncoded;
1724 out = pbEncoded;
1725 *out++ = ASN_SEQUENCEOF;
1726 CRYPT_EncodeLen(dataLen, out, &lenBytes);
1727 out += lenBytes;
1728 for (i = 0; i < capabilities->cCapability; i++)
1730 DWORD size = dataLen;
1732 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType,
1733 NULL, &capabilities->rgCapability[i], 0, NULL,
1734 out, &size);
1735 out += size;
1736 dataLen -= size;
1738 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1739 CRYPT_FreeSpace(pEncodePara, pbEncoded);
1744 __EXCEPT_PAGE_FAULT
1746 SetLastError(STATUS_ACCESS_VIOLATION);
1748 __ENDTRY
1749 return ret;
1752 static BOOL WINAPI CRYPT_AsnEncodeNoticeNumbers(DWORD dwCertEncodingType,
1753 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1754 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1756 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
1757 DWORD bytesNeeded, dataLen, lenBytes, i;
1758 BOOL ret = TRUE;
1760 for (i = 0, dataLen = 0; ret && i < noticeRef->cNoticeNumbers; i++)
1762 DWORD size;
1764 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
1765 &noticeRef->rgNoticeNumbers[i], 0, NULL, NULL, &size);
1766 if (ret)
1767 dataLen += size;
1769 if (ret)
1771 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1772 bytesNeeded = 1 + lenBytes + dataLen;
1773 if (!pbEncoded)
1774 *pcbEncoded = bytesNeeded;
1775 else
1777 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1778 pcbEncoded, bytesNeeded)))
1780 BYTE *out;
1782 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1783 pbEncoded = *(BYTE **)pbEncoded;
1784 out = pbEncoded;
1785 *out++ = ASN_SEQUENCE;
1786 CRYPT_EncodeLen(dataLen, out, &lenBytes);
1787 out += lenBytes;
1788 for (i = 0; i < noticeRef->cNoticeNumbers; i++)
1790 DWORD size = dataLen;
1792 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
1793 &noticeRef->rgNoticeNumbers[i], 0, NULL, out, &size);
1794 out += size;
1795 dataLen -= size;
1797 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1798 CRYPT_FreeSpace(pEncodePara, pbEncoded);
1802 return ret;
1805 static BOOL WINAPI CRYPT_AsnEncodeNoticeReference(DWORD dwCertEncodingType,
1806 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1807 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1809 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
1810 BOOL ret;
1811 CERT_NAME_VALUE orgValue = { CERT_RDN_IA5_STRING,
1812 { 0, (LPBYTE)noticeRef->pszOrganization } };
1813 struct AsnEncodeSequenceItem items[] = {
1814 { &orgValue, CRYPT_AsnEncodeNameValue, 0 },
1815 { noticeRef, CRYPT_AsnEncodeNoticeNumbers, 0 },
1818 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1819 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
1820 pcbEncoded);
1821 return ret;
1824 static BOOL WINAPI CRYPT_AsnEncodePolicyQualifierUserNotice(
1825 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1826 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1827 DWORD *pcbEncoded)
1829 BOOL ret = FALSE;
1831 __TRY
1833 const CERT_POLICY_QUALIFIER_USER_NOTICE *notice = pvStructInfo;
1834 struct AsnEncodeSequenceItem items[2];
1835 CERT_NAME_VALUE displayTextValue;
1836 DWORD cItem = 0;
1838 if (notice->pNoticeReference)
1840 items[cItem].encodeFunc = CRYPT_AsnEncodeNoticeReference;
1841 items[cItem].pvStructInfo = notice->pNoticeReference;
1842 cItem++;
1844 if (notice->pszDisplayText)
1846 displayTextValue.dwValueType = CERT_RDN_BMP_STRING;
1847 displayTextValue.Value.cbData = 0;
1848 displayTextValue.Value.pbData = (LPBYTE)notice->pszDisplayText;
1849 items[cItem].encodeFunc = CRYPT_AsnEncodeNameValue;
1850 items[cItem].pvStructInfo = &displayTextValue;
1851 cItem++;
1853 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1854 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1856 __EXCEPT_PAGE_FAULT
1858 SetLastError(STATUS_ACCESS_VIOLATION);
1860 __ENDTRY
1861 return ret;
1864 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1865 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1866 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1868 BOOL ret = FALSE;
1870 __TRY
1872 const CRYPT_ATTRIBUTE *attr = pvStructInfo;
1874 if (!attr->pszObjId)
1875 SetLastError(E_INVALIDARG);
1876 else
1878 struct AsnEncodeSequenceItem items[2] = {
1879 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1880 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1883 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1884 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded,
1885 pcbEncoded);
1888 __EXCEPT_PAGE_FAULT
1890 SetLastError(STATUS_ACCESS_VIOLATION);
1892 __ENDTRY
1893 return ret;
1896 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1897 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1898 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1900 BOOL ret = FALSE;
1902 __TRY
1904 const CRYPT_ATTRIBUTES *attributes = pvStructInfo;
1905 struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
1906 sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
1908 ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
1909 &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1911 __EXCEPT_PAGE_FAULT
1913 SetLastError(STATUS_ACCESS_VIOLATION);
1915 __ENDTRY
1916 return ret;
1919 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1920 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
1921 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1922 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1923 DWORD *pcbEncoded)
1925 const CRYPT_CONTENT_INFO *info = pvStructInfo;
1926 struct AsnEncodeSequenceItem items[2] = {
1927 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1928 { NULL, NULL, 0 },
1930 struct AsnConstructedItem constructed = { 0 };
1931 DWORD cItem = 1;
1933 if (info->Content.cbData)
1935 constructed.tag = 0;
1936 constructed.pvStructInfo = &info->Content;
1937 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1938 items[cItem].pvStructInfo = &constructed;
1939 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1940 cItem++;
1942 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1943 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1946 BOOL CRYPT_AsnEncodePKCSDigestedData(const CRYPT_DIGESTED_DATA *digestedData,
1947 void *pvData, DWORD *pcbData)
1949 struct AsnEncodeSequenceItem items[] = {
1950 { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1951 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
1952 0 },
1953 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1954 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1957 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, ARRAY_SIZE(items), 0, NULL, pvData, pcbData);
1960 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1961 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1962 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1964 BOOL ret = FALSE;
1966 __TRY
1968 const CRYPT_CONTENT_INFO *info = pvStructInfo;
1970 if (!info->pszObjId)
1971 SetLastError(E_INVALIDARG);
1972 else
1973 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
1974 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1975 pcbEncoded);
1977 __EXCEPT_PAGE_FAULT
1979 SetLastError(STATUS_ACCESS_VIOLATION);
1981 __ENDTRY
1982 return ret;
1985 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1986 BYTE tag, DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
1987 DWORD *pcbEncoded)
1989 BOOL ret = TRUE;
1990 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1991 DWORD bytesNeeded, lenBytes, encodedLen;
1993 if (value->Value.cbData)
1994 encodedLen = value->Value.cbData / sizeof(WCHAR);
1995 else if (str)
1996 encodedLen = lstrlenW(str);
1997 else
1998 encodedLen = 0;
1999 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2000 bytesNeeded = 1 + lenBytes + encodedLen;
2001 if (!pbEncoded)
2002 *pcbEncoded = bytesNeeded;
2003 else
2005 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2006 pbEncoded, pcbEncoded, bytesNeeded)))
2008 DWORD i;
2010 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2011 pbEncoded = *(BYTE **)pbEncoded;
2012 *pbEncoded++ = tag;
2013 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
2014 pbEncoded += lenBytes;
2015 for (i = 0; i < encodedLen; i++)
2016 *pbEncoded++ = (BYTE)str[i];
2019 return ret;
2022 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
2023 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2024 DWORD *pcbEncoded)
2026 BOOL ret = TRUE;
2027 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2028 DWORD bytesNeeded, lenBytes, encodedLen;
2030 if (value->Value.cbData)
2031 encodedLen = value->Value.cbData / sizeof(WCHAR);
2032 else if (str)
2033 encodedLen = lstrlenW(str);
2034 else
2035 encodedLen = 0;
2036 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2037 bytesNeeded = 1 + lenBytes + encodedLen;
2038 if (!pbEncoded)
2039 *pcbEncoded = bytesNeeded;
2040 else
2042 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2043 pbEncoded, pcbEncoded, bytesNeeded)))
2045 DWORD i;
2046 BYTE *ptr;
2048 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2049 ptr = *(BYTE **)pbEncoded;
2050 else
2051 ptr = pbEncoded;
2052 *ptr++ = ASN_NUMERICSTRING;
2053 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2054 ptr += lenBytes;
2055 for (i = 0; ret && i < encodedLen; i++)
2057 if ('0' <= str[i] && str[i] <= '9')
2058 *ptr++ = (BYTE)str[i];
2059 else
2061 *pcbEncoded = i;
2062 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
2063 ret = FALSE;
2066 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2067 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2070 return ret;
2073 static inline BOOL isprintableW(WCHAR wc)
2075 return wc && wcschr( L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '()+,-./:=?", wc );
2078 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
2079 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2080 DWORD *pcbEncoded)
2082 BOOL ret = TRUE;
2083 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2084 DWORD bytesNeeded, lenBytes, encodedLen;
2086 if (value->Value.cbData)
2087 encodedLen = value->Value.cbData / sizeof(WCHAR);
2088 else if (str)
2089 encodedLen = lstrlenW(str);
2090 else
2091 encodedLen = 0;
2092 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2093 bytesNeeded = 1 + lenBytes + encodedLen;
2094 if (!pbEncoded)
2095 *pcbEncoded = bytesNeeded;
2096 else
2098 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2099 pbEncoded, pcbEncoded, bytesNeeded)))
2101 DWORD i;
2102 BYTE *ptr;
2104 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2105 ptr = *(BYTE **)pbEncoded;
2106 else
2107 ptr = pbEncoded;
2108 *ptr++ = ASN_PRINTABLESTRING;
2109 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2110 ptr += lenBytes;
2111 for (i = 0; ret && i < encodedLen; i++)
2113 if (isprintableW(str[i]))
2114 *ptr++ = (BYTE)str[i];
2115 else
2117 *pcbEncoded = i;
2118 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
2119 ret = FALSE;
2122 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2123 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2126 return ret;
2129 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
2130 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2131 DWORD *pcbEncoded)
2133 BOOL ret = TRUE;
2134 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2135 DWORD bytesNeeded, lenBytes, encodedLen;
2137 if (value->Value.cbData)
2138 encodedLen = value->Value.cbData / sizeof(WCHAR);
2139 else if (str)
2140 encodedLen = lstrlenW(str);
2141 else
2142 encodedLen = 0;
2143 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2144 bytesNeeded = 1 + lenBytes + encodedLen;
2145 if (!pbEncoded)
2146 *pcbEncoded = bytesNeeded;
2147 else
2149 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2150 pbEncoded, pcbEncoded, bytesNeeded)))
2152 DWORD i;
2153 BYTE *ptr;
2155 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2156 ptr = *(BYTE **)pbEncoded;
2157 else
2158 ptr = pbEncoded;
2159 *ptr++ = ASN_IA5STRING;
2160 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2161 ptr += lenBytes;
2162 for (i = 0; ret && i < encodedLen; i++)
2164 if (str[i] <= 0x7f)
2165 *ptr++ = (BYTE)str[i];
2166 else
2168 *pcbEncoded = i;
2169 SetLastError(CRYPT_E_INVALID_IA5_STRING);
2170 ret = FALSE;
2173 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2174 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2177 return ret;
2180 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
2181 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2182 DWORD *pcbEncoded)
2184 BOOL ret = TRUE;
2185 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2186 DWORD bytesNeeded, lenBytes, strLen;
2188 /* FIXME: doesn't handle composite characters */
2189 if (value->Value.cbData)
2190 strLen = value->Value.cbData / sizeof(WCHAR);
2191 else if (str)
2192 strLen = lstrlenW(str);
2193 else
2194 strLen = 0;
2195 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
2196 bytesNeeded = 1 + lenBytes + strLen * 4;
2197 if (!pbEncoded)
2198 *pcbEncoded = bytesNeeded;
2199 else
2201 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2202 pbEncoded, pcbEncoded, bytesNeeded)))
2204 DWORD i;
2206 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2207 pbEncoded = *(BYTE **)pbEncoded;
2208 *pbEncoded++ = ASN_UNIVERSALSTRING;
2209 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
2210 pbEncoded += lenBytes;
2211 for (i = 0; i < strLen; i++)
2213 *pbEncoded++ = 0;
2214 *pbEncoded++ = 0;
2215 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
2216 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
2220 return ret;
2223 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
2224 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2225 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2227 BOOL ret = FALSE;
2229 __TRY
2231 const CERT_NAME_VALUE *value = pvStructInfo;
2233 switch (value->dwValueType)
2235 case CERT_RDN_ANY_TYPE:
2236 case CERT_RDN_ENCODED_BLOB:
2237 case CERT_RDN_OCTET_STRING:
2238 SetLastError(CRYPT_E_NOT_CHAR_STRING);
2239 break;
2240 case CERT_RDN_NUMERIC_STRING:
2241 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
2242 pbEncoded, pcbEncoded);
2243 break;
2244 case CERT_RDN_PRINTABLE_STRING:
2245 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
2246 pbEncoded, pcbEncoded);
2247 break;
2248 case CERT_RDN_TELETEX_STRING:
2249 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
2250 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2251 break;
2252 case CERT_RDN_VIDEOTEX_STRING:
2253 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
2254 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2255 break;
2256 case CERT_RDN_IA5_STRING:
2257 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
2258 pbEncoded, pcbEncoded);
2259 break;
2260 case CERT_RDN_GRAPHIC_STRING:
2261 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
2262 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2263 break;
2264 case CERT_RDN_VISIBLE_STRING:
2265 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
2266 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2267 break;
2268 case CERT_RDN_GENERAL_STRING:
2269 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
2270 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2271 break;
2272 case CERT_RDN_UNIVERSAL_STRING:
2273 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
2274 pbEncoded, pcbEncoded);
2275 break;
2276 case CERT_RDN_BMP_STRING:
2277 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
2278 pbEncoded, pcbEncoded);
2279 break;
2280 case CERT_RDN_UTF8_STRING:
2281 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
2282 pbEncoded, pcbEncoded);
2283 break;
2284 default:
2285 SetLastError(CRYPT_E_ASN1_CHOICE);
2288 __EXCEPT_PAGE_FAULT
2290 SetLastError(STATUS_ACCESS_VIOLATION);
2292 __ENDTRY
2293 return ret;
2296 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
2297 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2298 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2300 BOOL ret;
2302 __TRY
2304 const CERT_NAME_INFO *info = pvStructInfo;
2305 DWORD bytesNeeded = 0, lenBytes, size, i;
2307 TRACE("encoding name with %ld RDNs\n", info->cRDN);
2308 ret = TRUE;
2309 for (i = 0; ret && i < info->cRDN; i++)
2311 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
2312 CRYPT_AsnEncodeNameValue, NULL, &size);
2313 if (ret)
2314 bytesNeeded += size;
2316 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2317 bytesNeeded += 1 + lenBytes;
2318 if (ret)
2320 if (!pbEncoded)
2321 *pcbEncoded = bytesNeeded;
2322 else
2324 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2325 pbEncoded, pcbEncoded, bytesNeeded)))
2327 BYTE *out;
2329 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2330 pbEncoded = *(BYTE **)pbEncoded;
2331 out = pbEncoded;
2332 *out++ = ASN_SEQUENCEOF;
2333 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
2334 out += lenBytes;
2335 for (i = 0; ret && i < info->cRDN; i++)
2337 size = bytesNeeded;
2338 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
2339 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, out, &size);
2340 if (ret)
2342 out += size;
2343 bytesNeeded -= size;
2346 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2347 CRYPT_FreeSpace(pEncodePara, pbEncoded);
2352 __EXCEPT_PAGE_FAULT
2354 SetLastError(STATUS_ACCESS_VIOLATION);
2355 ret = FALSE;
2357 __ENDTRY
2358 return ret;
2361 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
2362 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2363 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2365 BOOL val = *(const BOOL *)pvStructInfo, ret;
2367 TRACE("%d\n", val);
2369 if (!pbEncoded)
2371 *pcbEncoded = 3;
2372 ret = TRUE;
2374 else if (*pcbEncoded < 3)
2376 *pcbEncoded = 3;
2377 SetLastError(ERROR_MORE_DATA);
2378 ret = FALSE;
2380 else
2382 *pcbEncoded = 3;
2383 *pbEncoded++ = ASN_BOOL;
2384 *pbEncoded++ = 1;
2385 *pbEncoded++ = val ? 0xff : 0;
2386 ret = TRUE;
2388 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2389 return ret;
2392 static BOOL WINAPI CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType,
2393 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2394 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2396 const CERT_ALT_NAME_ENTRY *entry = pvStructInfo;
2397 BOOL ret;
2398 DWORD dataLen;
2399 BYTE tag;
2401 ret = TRUE;
2402 switch (entry->dwAltNameChoice)
2404 case CERT_ALT_NAME_RFC822_NAME:
2405 case CERT_ALT_NAME_DNS_NAME:
2406 case CERT_ALT_NAME_URL:
2407 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2408 if (entry->pwszURL)
2410 DWORD i;
2412 /* Not + 1: don't encode the NULL-terminator */
2413 dataLen = lstrlenW(entry->pwszURL);
2414 for (i = 0; ret && i < dataLen; i++)
2416 if (entry->pwszURL[i] > 0x7f)
2418 SetLastError(CRYPT_E_INVALID_IA5_STRING);
2419 ret = FALSE;
2420 *pcbEncoded = i;
2424 else
2425 dataLen = 0;
2426 break;
2427 case CERT_ALT_NAME_DIRECTORY_NAME:
2428 tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1);
2429 dataLen = entry->DirectoryName.cbData;
2430 break;
2431 case CERT_ALT_NAME_IP_ADDRESS:
2432 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2433 dataLen = entry->IPAddress.cbData;
2434 break;
2435 case CERT_ALT_NAME_REGISTERED_ID:
2437 struct AsnEncodeTagSwappedItem swapped =
2438 { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->pszRegisteredID,
2439 CRYPT_AsnEncodeOid };
2441 return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded,
2442 pcbEncoded);
2444 case CERT_ALT_NAME_OTHER_NAME:
2445 FIXME("name type %ld unimplemented\n", entry->dwAltNameChoice);
2446 return FALSE;
2447 default:
2448 SetLastError(E_INVALIDARG);
2449 return FALSE;
2451 if (ret)
2453 DWORD bytesNeeded, lenBytes;
2455 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2456 bytesNeeded = 1 + dataLen + lenBytes;
2457 if (!pbEncoded)
2458 *pcbEncoded = bytesNeeded;
2459 else if (*pcbEncoded < bytesNeeded)
2461 SetLastError(ERROR_MORE_DATA);
2462 *pcbEncoded = bytesNeeded;
2463 ret = FALSE;
2465 else
2467 *pbEncoded++ = tag;
2468 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2469 pbEncoded += lenBytes;
2470 switch (entry->dwAltNameChoice)
2472 case CERT_ALT_NAME_RFC822_NAME:
2473 case CERT_ALT_NAME_DNS_NAME:
2474 case CERT_ALT_NAME_URL:
2476 DWORD i;
2478 for (i = 0; i < dataLen; i++)
2479 *pbEncoded++ = (BYTE)entry->pwszURL[i];
2480 break;
2482 case CERT_ALT_NAME_DIRECTORY_NAME:
2483 memcpy(pbEncoded, entry->DirectoryName.pbData, dataLen);
2484 break;
2485 case CERT_ALT_NAME_IP_ADDRESS:
2486 memcpy(pbEncoded, entry->IPAddress.pbData, dataLen);
2487 break;
2489 if (ret)
2490 *pcbEncoded = bytesNeeded;
2493 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2494 return ret;
2497 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
2498 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2499 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2501 BOOL ret;
2503 __TRY
2505 const CERT_AUTHORITY_KEY_ID_INFO *info = pvStructInfo;
2506 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2507 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2508 struct AsnConstructedItem constructed = { 0 };
2509 DWORD cItem = 0, cSwapped = 0;
2511 if (info->KeyId.cbData)
2513 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2514 swapped[cSwapped].pvStructInfo = &info->KeyId;
2515 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
2516 items[cItem].pvStructInfo = &swapped[cSwapped];
2517 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2518 cSwapped++;
2519 cItem++;
2521 if (info->CertIssuer.cbData)
2523 constructed.tag = 1;
2524 constructed.pvStructInfo = &info->CertIssuer;
2525 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2526 items[cItem].pvStructInfo = &constructed;
2527 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2528 cItem++;
2530 if (info->CertSerialNumber.cbData)
2532 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2533 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2534 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2535 items[cItem].pvStructInfo = &swapped[cSwapped];
2536 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2537 cSwapped++;
2538 cItem++;
2540 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2541 pEncodePara, pbEncoded, pcbEncoded);
2543 __EXCEPT_PAGE_FAULT
2545 SetLastError(STATUS_ACCESS_VIOLATION);
2546 ret = FALSE;
2548 __ENDTRY
2549 return ret;
2552 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2553 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2554 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2556 BOOL ret;
2558 __TRY
2560 const CERT_ALT_NAME_INFO *info = pvStructInfo;
2561 DWORD bytesNeeded, dataLen, lenBytes, i;
2563 ret = TRUE;
2564 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2565 * can't encode an erroneous entry index if it's bigger than this.
2567 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2569 DWORD len;
2571 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, NULL,
2572 &info->rgAltEntry[i], 0, NULL, NULL, &len);
2573 if (ret)
2574 dataLen += len;
2575 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2577 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2578 * the bad character, now set the index of the bad
2579 * entry
2581 *pcbEncoded = (BYTE)i <<
2582 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2585 if (ret)
2587 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2588 bytesNeeded = 1 + lenBytes + dataLen;
2589 if (!pbEncoded)
2591 *pcbEncoded = bytesNeeded;
2592 ret = TRUE;
2594 else
2596 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2597 pbEncoded, pcbEncoded, bytesNeeded)))
2599 BYTE *out;
2601 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2602 pbEncoded = *(BYTE **)pbEncoded;
2603 out = pbEncoded;
2604 *out++ = ASN_SEQUENCEOF;
2605 CRYPT_EncodeLen(dataLen, out, &lenBytes);
2606 out += lenBytes;
2607 for (i = 0; ret && i < info->cAltEntry; i++)
2609 DWORD len = dataLen;
2611 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType,
2612 NULL, &info->rgAltEntry[i], 0, NULL, out, &len);
2613 if (ret)
2615 out += len;
2616 dataLen -= len;
2619 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2620 CRYPT_FreeSpace(pEncodePara, pbEncoded);
2625 __EXCEPT_PAGE_FAULT
2627 SetLastError(STATUS_ACCESS_VIOLATION);
2628 ret = FALSE;
2630 __ENDTRY
2631 return ret;
2634 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2635 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2636 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2638 BOOL ret;
2640 __TRY
2642 const CERT_AUTHORITY_KEY_ID2_INFO *info = pvStructInfo;
2643 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2644 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2645 DWORD cItem = 0, cSwapped = 0;
2647 if (info->KeyId.cbData)
2649 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2650 swapped[cSwapped].pvStructInfo = &info->KeyId;
2651 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
2652 items[cItem].pvStructInfo = &swapped[cSwapped];
2653 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2654 cSwapped++;
2655 cItem++;
2657 if (info->AuthorityCertIssuer.cAltEntry)
2659 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2660 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2661 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2662 items[cItem].pvStructInfo = &swapped[cSwapped];
2663 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2664 cSwapped++;
2665 cItem++;
2667 if (info->AuthorityCertSerialNumber.cbData)
2669 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2670 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2671 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2672 items[cItem].pvStructInfo = &swapped[cSwapped];
2673 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2674 cSwapped++;
2675 cItem++;
2677 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2678 pEncodePara, pbEncoded, pcbEncoded);
2680 __EXCEPT_PAGE_FAULT
2682 SetLastError(STATUS_ACCESS_VIOLATION);
2683 ret = FALSE;
2685 __ENDTRY
2686 return ret;
2689 static BOOL CRYPT_AsnEncodeAccessDescription(
2690 const CERT_ACCESS_DESCRIPTION *descr, BYTE *pbEncoded, DWORD *pcbEncoded)
2692 struct AsnEncodeSequenceItem items[] = {
2693 { descr->pszAccessMethod, CRYPT_AsnEncodeOid, 0 },
2694 { &descr->AccessLocation, CRYPT_AsnEncodeAltNameEntry, 0 },
2697 if (!descr->pszAccessMethod)
2699 SetLastError(E_INVALIDARG);
2700 return FALSE;
2702 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, ARRAY_SIZE(items), 0, NULL, pbEncoded, pcbEncoded);
2705 static BOOL WINAPI CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType,
2706 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2707 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2709 BOOL ret;
2711 __TRY
2713 DWORD bytesNeeded, dataLen, lenBytes, i;
2714 const CERT_AUTHORITY_INFO_ACCESS *info = pvStructInfo;
2716 ret = TRUE;
2717 for (i = 0, dataLen = 0; ret && i < info->cAccDescr; i++)
2719 DWORD size;
2721 ret = CRYPT_AsnEncodeAccessDescription(&info->rgAccDescr[i], NULL,
2722 &size);
2723 if (ret)
2724 dataLen += size;
2726 if (ret)
2728 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2729 bytesNeeded = 1 + lenBytes + dataLen;
2730 if (!pbEncoded)
2731 *pcbEncoded = bytesNeeded;
2732 else
2734 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2735 pbEncoded, pcbEncoded, bytesNeeded)))
2737 BYTE *out;
2739 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2740 pbEncoded = *(BYTE **)pbEncoded;
2741 out = pbEncoded;
2742 *out++ = ASN_SEQUENCEOF;
2743 CRYPT_EncodeLen(dataLen, out, &lenBytes);
2744 out += lenBytes;
2745 for (i = 0; i < info->cAccDescr; i++)
2747 DWORD size = dataLen;
2749 ret = CRYPT_AsnEncodeAccessDescription(
2750 &info->rgAccDescr[i], out, &size);
2751 out += size;
2752 dataLen -= size;
2754 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2755 CRYPT_FreeSpace(pEncodePara, pbEncoded);
2760 __EXCEPT_PAGE_FAULT
2762 SetLastError(STATUS_ACCESS_VIOLATION);
2763 ret = FALSE;
2765 __ENDTRY
2766 return ret;
2769 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2770 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2771 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2773 BOOL ret;
2775 __TRY
2777 const CERT_BASIC_CONSTRAINTS_INFO *info = pvStructInfo;
2778 struct AsnEncodeSequenceItem items[3] = {
2779 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2780 { 0 }
2782 DWORD cItem = 1;
2784 if (info->fPathLenConstraint)
2786 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2787 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2788 cItem++;
2790 if (info->cSubtreesConstraint)
2792 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2793 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2794 cItem++;
2796 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2797 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2799 __EXCEPT_PAGE_FAULT
2801 SetLastError(STATUS_ACCESS_VIOLATION);
2802 ret = FALSE;
2804 __ENDTRY
2805 return ret;
2808 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2809 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2810 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2812 BOOL ret;
2814 __TRY
2816 const CERT_BASIC_CONSTRAINTS2_INFO *info = pvStructInfo;
2817 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2818 DWORD cItem = 0;
2820 if (info->fCA)
2822 items[cItem].pvStructInfo = &info->fCA;
2823 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2824 cItem++;
2826 if (info->fPathLenConstraint)
2828 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2829 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2830 cItem++;
2832 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2833 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2835 __EXCEPT_PAGE_FAULT
2837 SetLastError(STATUS_ACCESS_VIOLATION);
2838 ret = FALSE;
2840 __ENDTRY
2841 return ret;
2844 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType,
2845 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2846 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2848 const CERT_POLICY_INFO *info = pvStructInfo;
2849 BOOL ret;
2851 if (!info->cPolicyQualifier)
2853 *pcbEncoded = 0;
2854 ret = TRUE;
2856 else
2858 struct AsnEncodeSequenceItem items[2] = {
2859 { NULL, CRYPT_AsnEncodeOid, 0 },
2860 { NULL, CRYPT_CopyEncodedBlob, 0 },
2862 DWORD bytesNeeded = 0, lenBytes, size, i;
2864 ret = TRUE;
2865 for (i = 0; ret && i < info->cPolicyQualifier; i++)
2867 items[0].pvStructInfo =
2868 info->rgPolicyQualifier[i].pszPolicyQualifierId;
2869 items[1].pvStructInfo = &info->rgPolicyQualifier[i].Qualifier;
2870 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items),
2871 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
2872 if (ret)
2873 bytesNeeded += size;
2875 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2876 bytesNeeded += 1 + lenBytes;
2877 if (ret)
2879 if (!pbEncoded)
2880 *pcbEncoded = bytesNeeded;
2881 else
2883 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2884 pbEncoded, pcbEncoded, bytesNeeded)))
2886 BYTE *out;
2888 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2889 pbEncoded = *(BYTE **)pbEncoded;
2890 out = pbEncoded;
2891 *out++ = ASN_SEQUENCEOF;
2892 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
2893 out += lenBytes;
2894 for (i = 0; ret && i < info->cPolicyQualifier; i++)
2896 items[0].pvStructInfo =
2897 info->rgPolicyQualifier[i].pszPolicyQualifierId;
2898 items[1].pvStructInfo =
2899 &info->rgPolicyQualifier[i].Qualifier;
2900 size = bytesNeeded;
2901 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items),
2902 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, out, &size);
2903 if (ret)
2905 out += size;
2906 bytesNeeded -= size;
2909 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2910 CRYPT_FreeSpace(pEncodePara, pbEncoded);
2915 return ret;
2918 static BOOL CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType,
2919 const CERT_POLICY_INFO *info, DWORD dwFlags, BYTE *pbEncoded,
2920 DWORD *pcbEncoded)
2922 struct AsnEncodeSequenceItem items[2] = {
2923 { info->pszPolicyIdentifier, CRYPT_AsnEncodeOid, 0 },
2924 { info, CRYPT_AsnEncodeCertPolicyQualifiers, 0 },
2926 BOOL ret;
2928 if (!info->pszPolicyIdentifier)
2930 SetLastError(E_INVALIDARG);
2931 return FALSE;
2933 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items), dwFlags, NULL, pbEncoded, pcbEncoded);
2934 return ret;
2937 static BOOL WINAPI CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType,
2938 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2939 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2941 BOOL ret = FALSE;
2943 __TRY
2945 const CERT_POLICIES_INFO *info = pvStructInfo;
2946 DWORD bytesNeeded = 0, lenBytes, size, i;
2948 ret = TRUE;
2949 for (i = 0; ret && i < info->cPolicyInfo; i++)
2951 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
2952 &info->rgPolicyInfo[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
2953 &size);
2954 if (ret)
2955 bytesNeeded += size;
2957 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2958 bytesNeeded += 1 + lenBytes;
2959 if (ret)
2961 if (!pbEncoded)
2962 *pcbEncoded = bytesNeeded;
2963 else
2965 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2966 pbEncoded, pcbEncoded, bytesNeeded)))
2968 BYTE *out;
2970 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2971 pbEncoded = *(BYTE **)pbEncoded;
2972 out = pbEncoded;
2973 *out++ = ASN_SEQUENCEOF;
2974 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
2975 out += lenBytes;
2976 for (i = 0; ret && i < info->cPolicyInfo; i++)
2978 size = bytesNeeded;
2979 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
2980 &info->rgPolicyInfo[i],
2981 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, out, &size);
2982 if (ret)
2984 out += size;
2985 bytesNeeded -= size;
2988 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2989 CRYPT_FreeSpace(pEncodePara, pbEncoded);
2994 __EXCEPT_PAGE_FAULT
2996 SetLastError(STATUS_ACCESS_VIOLATION);
2998 __ENDTRY
2999 return ret;
3002 static BOOL CRYPT_AsnEncodeCertPolicyMapping(DWORD dwCertEncodingType,
3003 const CERT_POLICY_MAPPING *mapping, DWORD dwFlags, BYTE *pbEncoded,
3004 DWORD *pcbEncoded)
3006 struct AsnEncodeSequenceItem items[] = {
3007 { mapping->pszIssuerDomainPolicy, CRYPT_AsnEncodeOid, 0 },
3008 { mapping->pszSubjectDomainPolicy, CRYPT_AsnEncodeOid, 0 },
3011 if (!mapping->pszIssuerDomainPolicy || !mapping->pszSubjectDomainPolicy)
3013 SetLastError(E_INVALIDARG);
3014 return FALSE;
3016 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items), dwFlags, NULL, pbEncoded, pcbEncoded);
3019 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyMappings(DWORD dwCertEncodingType,
3020 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3021 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3023 BOOL ret = FALSE;
3025 __TRY
3027 const CERT_POLICY_MAPPINGS_INFO *info = pvStructInfo;
3028 DWORD bytesNeeded = 0, lenBytes, size, i;
3030 ret = TRUE;
3031 for (i = 0; ret && i < info->cPolicyMapping; i++)
3033 ret = CRYPT_AsnEncodeCertPolicyMapping(dwCertEncodingType,
3034 &info->rgPolicyMapping[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
3035 NULL, &size);
3036 if (ret)
3037 bytesNeeded += size;
3039 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3040 bytesNeeded += 1 + lenBytes;
3041 if (ret)
3043 if (!pbEncoded)
3044 *pcbEncoded = bytesNeeded;
3045 else
3047 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3048 pbEncoded, pcbEncoded, bytesNeeded)))
3050 BYTE *out;
3052 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3053 pbEncoded = *(BYTE **)pbEncoded;
3054 out = pbEncoded;
3055 *out++ = ASN_SEQUENCEOF;
3056 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
3057 out += lenBytes;
3058 for (i = 0; ret && i < info->cPolicyMapping; i++)
3060 size = bytesNeeded;
3061 ret = CRYPT_AsnEncodeCertPolicyMapping(
3062 dwCertEncodingType, &info->rgPolicyMapping[i],
3063 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, out, &size);
3064 if (ret)
3066 out += size;
3067 bytesNeeded -= size;
3070 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
3071 CRYPT_FreeSpace(pEncodePara, pbEncoded);
3076 __EXCEPT_PAGE_FAULT
3078 SetLastError(STATUS_ACCESS_VIOLATION);
3080 __ENDTRY
3081 return ret;
3084 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyConstraints(
3085 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3086 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3087 DWORD *pcbEncoded)
3089 BOOL ret = FALSE;
3091 __TRY
3093 const CERT_POLICY_CONSTRAINTS_INFO *info = pvStructInfo;
3094 struct AsnEncodeSequenceItem items[2];
3095 struct AsnEncodeTagSwappedItem swapped[2];
3096 DWORD cItem = 0, cSwapped = 0;
3098 if (info->fRequireExplicitPolicy)
3100 swapped[cSwapped].tag = ASN_CONTEXT | 0;
3101 swapped[cSwapped].pvStructInfo =
3102 &info->dwRequireExplicitPolicySkipCerts;
3103 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3104 items[cItem].pvStructInfo = &swapped[cSwapped];
3105 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3106 cSwapped++;
3107 cItem++;
3109 if (info->fInhibitPolicyMapping)
3111 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3112 swapped[cSwapped].pvStructInfo =
3113 &info->dwInhibitPolicyMappingSkipCerts;
3114 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3115 items[cItem].pvStructInfo = &swapped[cSwapped];
3116 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3117 cSwapped++;
3118 cItem++;
3120 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3121 dwFlags, NULL, pbEncoded, pcbEncoded);
3123 __EXCEPT_PAGE_FAULT
3125 SetLastError(STATUS_ACCESS_VIOLATION);
3127 __ENDTRY
3128 return ret;
3131 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey_Bcrypt(DWORD dwCertEncodingType,
3132 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3133 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3135 BOOL ret;
3137 __TRY
3139 const BCRYPT_RSAKEY_BLOB *hdr = pvStructInfo;
3141 BYTE *pubexp = (BYTE*)pvStructInfo + sizeof(BCRYPT_RSAKEY_BLOB);
3142 BYTE *modulus = (BYTE*)pvStructInfo + sizeof(BCRYPT_RSAKEY_BLOB) + hdr->cbPublicExp;
3143 BYTE *pubexp_be = CryptMemAlloc(hdr->cbPublicExp);
3144 BYTE *modulus_be = CryptMemAlloc(hdr->cbModulus);
3145 CRYPT_INTEGER_BLOB pubexp_int = { hdr->cbPublicExp, pubexp_be };
3146 CRYPT_INTEGER_BLOB modulus_int = { hdr->cbModulus, modulus_be};
3148 struct AsnEncodeSequenceItem items[] = {
3149 { &modulus_int, CRYPT_AsnEncodeUnsignedInteger, 0 },
3150 { &pubexp_int, CRYPT_AsnEncodeInteger, 0 },
3153 /* CNG_RSA_PUBLIC_KEY_BLOB stores the exponent and modulus
3154 * in big-endian format, so we need to convert them
3155 * to little-endian format before encoding
3157 CRYPT_CopyReversed(pubexp_be, pubexp, hdr->cbPublicExp);
3158 CRYPT_CopyReversed(modulus_be, modulus, hdr->cbModulus);
3160 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3161 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3163 CryptMemFree(pubexp_be);
3164 CryptMemFree(modulus_be);
3166 __EXCEPT_PAGE_FAULT
3168 SetLastError(STATUS_ACCESS_VIOLATION);
3169 ret = FALSE;
3171 __ENDTRY
3172 return ret;
3177 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
3178 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3179 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3181 BOOL ret;
3183 __TRY
3185 const BLOBHEADER *hdr = pvStructInfo;
3187 if (hdr->bType != PUBLICKEYBLOB)
3189 SetLastError(E_INVALIDARG);
3190 ret = FALSE;
3192 else
3194 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
3195 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
3196 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
3197 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
3198 struct AsnEncodeSequenceItem items[] = {
3199 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
3200 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
3203 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3204 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3207 __EXCEPT_PAGE_FAULT
3209 SetLastError(STATUS_ACCESS_VIOLATION);
3210 ret = FALSE;
3212 __ENDTRY
3213 return ret;
3216 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
3217 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3218 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3220 BOOL ret;
3222 __TRY
3224 const CRYPT_DATA_BLOB *blob = pvStructInfo;
3225 DWORD bytesNeeded, lenBytes;
3227 TRACE("(%ld, %p), %08lx, %p, %p, %ld\n", blob->cbData, blob->pbData,
3228 dwFlags, pEncodePara, pbEncoded, pbEncoded ? *pcbEncoded : 0);
3230 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
3231 bytesNeeded = 1 + lenBytes + blob->cbData;
3232 if (!pbEncoded)
3234 *pcbEncoded = bytesNeeded;
3235 ret = TRUE;
3237 else
3239 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3240 pcbEncoded, bytesNeeded)))
3242 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3243 pbEncoded = *(BYTE **)pbEncoded;
3244 *pbEncoded++ = ASN_OCTETSTRING;
3245 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
3246 pbEncoded += lenBytes;
3247 if (blob->cbData)
3248 memcpy(pbEncoded, blob->pbData, blob->cbData);
3252 __EXCEPT_PAGE_FAULT
3254 SetLastError(STATUS_ACCESS_VIOLATION);
3255 ret = FALSE;
3257 __ENDTRY
3258 TRACE("returning %d (%08lx)\n", ret, GetLastError());
3259 return ret;
3262 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
3263 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3264 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3266 BOOL ret;
3268 __TRY
3270 const CRYPT_BIT_BLOB *blob = pvStructInfo;
3271 DWORD bytesNeeded, lenBytes, dataBytes;
3272 BYTE unusedBits;
3274 /* yep, MS allows cUnusedBits to be >= 8 */
3275 if (!blob->cUnusedBits)
3277 dataBytes = blob->cbData;
3278 unusedBits = 0;
3280 else if (blob->cbData * 8 > blob->cUnusedBits)
3282 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
3283 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
3284 blob->cUnusedBits;
3286 else
3288 dataBytes = 0;
3289 unusedBits = 0;
3291 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
3292 bytesNeeded = 1 + lenBytes + dataBytes + 1;
3293 if (!pbEncoded)
3295 *pcbEncoded = bytesNeeded;
3296 ret = TRUE;
3298 else
3300 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3301 pcbEncoded, bytesNeeded)))
3303 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3304 pbEncoded = *(BYTE **)pbEncoded;
3305 *pbEncoded++ = ASN_BITSTRING;
3306 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
3307 pbEncoded += lenBytes;
3308 *pbEncoded++ = unusedBits;
3309 if (dataBytes)
3311 BYTE mask = 0xff << unusedBits;
3313 if (dataBytes > 1)
3315 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
3316 pbEncoded += dataBytes - 1;
3318 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
3323 __EXCEPT_PAGE_FAULT
3325 SetLastError(STATUS_ACCESS_VIOLATION);
3326 ret = FALSE;
3328 __ENDTRY
3329 return ret;
3332 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
3333 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3334 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3336 BOOL ret;
3338 __TRY
3340 const CRYPT_BIT_BLOB *blob = pvStructInfo;
3341 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
3343 ret = TRUE;
3344 if (newBlob.cbData)
3346 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
3347 if (newBlob.pbData)
3349 DWORD i;
3351 for (i = 0; i < newBlob.cbData; i++)
3352 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
3354 else
3355 ret = FALSE;
3357 if (ret)
3358 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
3359 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3360 CryptMemFree(newBlob.pbData);
3362 __EXCEPT_PAGE_FAULT
3364 SetLastError(STATUS_ACCESS_VIOLATION);
3365 ret = FALSE;
3367 __ENDTRY
3368 return ret;
3371 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
3372 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3373 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3375 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
3377 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
3378 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3381 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
3382 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3383 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3385 BOOL ret;
3387 __TRY
3389 DWORD significantBytes, lenBytes, bytesNeeded;
3390 BYTE padByte = 0;
3391 BOOL pad = FALSE;
3392 const CRYPT_INTEGER_BLOB *blob = pvStructInfo;
3394 significantBytes = blob->cbData;
3395 if (significantBytes)
3397 if (blob->pbData[significantBytes - 1] & 0x80)
3399 /* negative, lop off leading (little-endian) 0xffs */
3400 for (; significantBytes > 0 &&
3401 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
3403 if (blob->pbData[significantBytes - 1] < 0x80)
3405 padByte = 0xff;
3406 pad = TRUE;
3409 else
3411 /* positive, lop off leading (little-endian) zeroes */
3412 for (; significantBytes > 0 &&
3413 !blob->pbData[significantBytes - 1]; significantBytes--)
3415 if (significantBytes == 0)
3416 significantBytes = 1;
3417 if (blob->pbData[significantBytes - 1] > 0x7f)
3419 padByte = 0;
3420 pad = TRUE;
3424 if (pad)
3425 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3426 else
3427 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3428 bytesNeeded = 1 + lenBytes + significantBytes;
3429 if (pad)
3430 bytesNeeded++;
3431 if (!pbEncoded)
3433 *pcbEncoded = bytesNeeded;
3434 ret = TRUE;
3436 else
3438 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3439 pcbEncoded, bytesNeeded)))
3441 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3442 pbEncoded = *(BYTE **)pbEncoded;
3443 *pbEncoded++ = ASN_INTEGER;
3444 if (pad)
3446 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3447 pbEncoded += lenBytes;
3448 *pbEncoded++ = padByte;
3450 else
3452 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3453 pbEncoded += lenBytes;
3455 for (; significantBytes > 0; significantBytes--)
3456 *(pbEncoded++) = blob->pbData[significantBytes - 1];
3460 __EXCEPT_PAGE_FAULT
3462 SetLastError(STATUS_ACCESS_VIOLATION);
3463 ret = FALSE;
3465 __ENDTRY
3466 return ret;
3469 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
3470 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3471 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3473 BOOL ret;
3475 __TRY
3477 DWORD significantBytes, lenBytes, bytesNeeded;
3478 BOOL pad = FALSE;
3479 const CRYPT_INTEGER_BLOB *blob = pvStructInfo;
3481 significantBytes = blob->cbData;
3482 if (significantBytes)
3484 /* positive, lop off leading (little-endian) zeroes */
3485 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
3486 significantBytes--)
3488 if (significantBytes == 0)
3489 significantBytes = 1;
3490 if (blob->pbData[significantBytes - 1] > 0x7f)
3491 pad = TRUE;
3493 if (pad)
3494 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3495 else
3496 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3497 bytesNeeded = 1 + lenBytes + significantBytes;
3498 if (pad)
3499 bytesNeeded++;
3500 if (!pbEncoded)
3502 *pcbEncoded = bytesNeeded;
3503 ret = TRUE;
3505 else
3507 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3508 pcbEncoded, bytesNeeded)))
3510 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3511 pbEncoded = *(BYTE **)pbEncoded;
3512 *pbEncoded++ = ASN_INTEGER;
3513 if (pad)
3515 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3516 pbEncoded += lenBytes;
3517 *pbEncoded++ = 0;
3519 else
3521 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3522 pbEncoded += lenBytes;
3524 for (; significantBytes > 0; significantBytes--)
3525 *(pbEncoded++) = blob->pbData[significantBytes - 1];
3529 __EXCEPT_PAGE_FAULT
3531 SetLastError(STATUS_ACCESS_VIOLATION);
3532 ret = FALSE;
3534 __ENDTRY
3535 return ret;
3538 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
3539 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3540 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3542 CRYPT_INTEGER_BLOB blob;
3543 BOOL ret;
3545 /* Encode as an unsigned integer, then change the tag to enumerated */
3546 blob.cbData = sizeof(DWORD);
3547 blob.pbData = (BYTE *)pvStructInfo;
3548 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
3549 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3550 if (ret && pbEncoded)
3552 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3553 pbEncoded = *(BYTE **)pbEncoded;
3554 pbEncoded[0] = ASN_ENUMERATED;
3556 return ret;
3559 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
3560 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3561 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3563 BOOL ret;
3565 __TRY
3567 SYSTEMTIME sysTime;
3568 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ. I use a
3569 * temporary buffer because the output buffer is not NULL-terminated.
3571 static const DWORD bytesNeeded = 15;
3572 char buf[40];
3574 if (!pbEncoded)
3576 *pcbEncoded = bytesNeeded;
3577 ret = TRUE;
3579 else
3581 /* Sanity check the year, this is a two-digit year format */
3582 ret = FileTimeToSystemTime(pvStructInfo, &sysTime);
3583 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
3585 SetLastError(CRYPT_E_BAD_ENCODE);
3586 ret = FALSE;
3588 if (ret)
3590 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3591 pbEncoded, pcbEncoded, bytesNeeded)))
3593 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3594 pbEncoded = *(BYTE **)pbEncoded;
3595 buf[0] = ASN_UTCTIME;
3596 buf[1] = bytesNeeded - 2;
3597 snprintf(buf + 2, sizeof(buf) - 2,
3598 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
3599 sysTime.wYear - 2000 : sysTime.wYear - 1900,
3600 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3601 sysTime.wMinute, sysTime.wSecond);
3602 memcpy(pbEncoded, buf, bytesNeeded);
3607 __EXCEPT_PAGE_FAULT
3609 SetLastError(STATUS_ACCESS_VIOLATION);
3610 ret = FALSE;
3612 __ENDTRY
3613 return ret;
3616 static BOOL CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
3617 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3618 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3620 BOOL ret;
3622 __TRY
3624 SYSTEMTIME sysTime;
3625 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ. I use a
3626 * temporary buffer because the output buffer is not NULL-terminated.
3628 static const DWORD bytesNeeded = 17;
3629 char buf[40];
3631 if (!pbEncoded)
3633 *pcbEncoded = bytesNeeded;
3634 ret = TRUE;
3636 else
3638 ret = FileTimeToSystemTime(pvStructInfo, &sysTime);
3639 if (ret)
3640 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3641 pcbEncoded, bytesNeeded);
3642 if (ret)
3644 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3645 pbEncoded = *(BYTE **)pbEncoded;
3646 buf[0] = ASN_GENERALTIME;
3647 buf[1] = bytesNeeded - 2;
3648 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
3649 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3650 sysTime.wMinute, sysTime.wSecond);
3651 memcpy(pbEncoded, buf, bytesNeeded);
3655 __EXCEPT_PAGE_FAULT
3657 SetLastError(STATUS_ACCESS_VIOLATION);
3658 ret = FALSE;
3660 __ENDTRY
3661 return ret;
3664 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
3665 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3666 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3668 BOOL ret;
3670 __TRY
3672 SYSTEMTIME sysTime;
3674 /* Check the year, if it's in the UTCTime range call that encode func */
3675 if (!FileTimeToSystemTime(pvStructInfo, &sysTime))
3676 return FALSE;
3677 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
3678 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
3679 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3680 else
3681 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
3682 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
3683 pcbEncoded);
3685 __EXCEPT_PAGE_FAULT
3687 SetLastError(STATUS_ACCESS_VIOLATION);
3688 ret = FALSE;
3690 __ENDTRY
3691 return ret;
3694 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
3695 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3696 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3698 BOOL ret;
3700 __TRY
3702 DWORD bytesNeeded, dataLen, lenBytes, i;
3703 const CRYPT_SEQUENCE_OF_ANY *seq = pvStructInfo;
3705 for (i = 0, dataLen = 0; i < seq->cValue; i++)
3706 dataLen += seq->rgValue[i].cbData;
3707 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3708 bytesNeeded = 1 + lenBytes + dataLen;
3709 if (!pbEncoded)
3711 *pcbEncoded = bytesNeeded;
3712 ret = TRUE;
3714 else
3716 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3717 pcbEncoded, bytesNeeded)))
3719 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3720 pbEncoded = *(BYTE **)pbEncoded;
3721 *pbEncoded++ = ASN_SEQUENCEOF;
3722 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
3723 pbEncoded += lenBytes;
3724 for (i = 0; i < seq->cValue; i++)
3726 memcpy(pbEncoded, seq->rgValue[i].pbData,
3727 seq->rgValue[i].cbData);
3728 pbEncoded += seq->rgValue[i].cbData;
3733 __EXCEPT_PAGE_FAULT
3735 SetLastError(STATUS_ACCESS_VIOLATION);
3736 ret = FALSE;
3738 __ENDTRY
3739 return ret;
3742 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
3743 BYTE *pbEncoded, DWORD *pcbEncoded)
3745 BOOL ret = TRUE;
3746 struct AsnEncodeSequenceItem items[3] = { { 0 } };
3747 struct AsnConstructedItem constructed = { 0 };
3748 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
3749 DWORD cItem = 0, cSwapped = 0;
3751 switch (distPoint->DistPointName.dwDistPointNameChoice)
3753 case CRL_DIST_POINT_NO_NAME:
3754 /* do nothing */
3755 break;
3756 case CRL_DIST_POINT_FULL_NAME:
3757 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3758 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.FullName;
3759 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3760 constructed.tag = 0;
3761 constructed.pvStructInfo = &swapped[cSwapped];
3762 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3763 items[cItem].pvStructInfo = &constructed;
3764 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3765 cSwapped++;
3766 cItem++;
3767 break;
3768 case CRL_DIST_POINT_ISSUER_RDN_NAME:
3769 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3770 ret = FALSE;
3771 break;
3772 default:
3773 ret = FALSE;
3775 if (ret && distPoint->ReasonFlags.cbData)
3777 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3778 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
3779 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3780 items[cItem].pvStructInfo = &swapped[cSwapped];
3781 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3782 cSwapped++;
3783 cItem++;
3785 if (ret && distPoint->CRLIssuer.cAltEntry)
3787 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
3788 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
3789 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3790 items[cItem].pvStructInfo = &swapped[cSwapped];
3791 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3792 cSwapped++;
3793 cItem++;
3795 if (ret)
3796 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
3797 pbEncoded, pcbEncoded);
3798 return ret;
3801 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
3802 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3803 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3805 BOOL ret;
3807 __TRY
3809 const CRL_DIST_POINTS_INFO *info = pvStructInfo;
3811 if (!info->cDistPoint)
3813 SetLastError(E_INVALIDARG);
3814 ret = FALSE;
3816 else
3818 DWORD bytesNeeded, dataLen, lenBytes, i;
3820 ret = TRUE;
3821 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
3823 DWORD len;
3825 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
3826 &len);
3827 if (ret)
3828 dataLen += len;
3829 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
3831 /* Have to propagate index of failing character */
3832 *pcbEncoded = len;
3835 if (ret)
3837 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3838 bytesNeeded = 1 + lenBytes + dataLen;
3839 if (!pbEncoded)
3841 *pcbEncoded = bytesNeeded;
3842 ret = TRUE;
3844 else
3846 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3847 pbEncoded, pcbEncoded, bytesNeeded)))
3849 BYTE *out;
3851 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3852 pbEncoded = *(BYTE **)pbEncoded;
3853 out = pbEncoded;
3854 *out++ = ASN_SEQUENCEOF;
3855 CRYPT_EncodeLen(dataLen, out, &lenBytes);
3856 out += lenBytes;
3857 for (i = 0; ret && i < info->cDistPoint; i++)
3859 DWORD len = dataLen;
3861 ret = CRYPT_AsnEncodeDistPoint(
3862 &info->rgDistPoint[i], out, &len);
3863 if (ret)
3865 out += len;
3866 dataLen -= len;
3869 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
3870 CRYPT_FreeSpace(pEncodePara, pbEncoded);
3876 __EXCEPT_PAGE_FAULT
3878 SetLastError(STATUS_ACCESS_VIOLATION);
3879 ret = FALSE;
3881 __ENDTRY
3882 return ret;
3885 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3886 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3887 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3889 BOOL ret;
3891 __TRY
3893 const CERT_ENHKEY_USAGE *usage = pvStructInfo;
3894 DWORD bytesNeeded = 0, lenBytes, size, i;
3896 ret = TRUE;
3897 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3899 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3900 usage->rgpszUsageIdentifier[i],
3901 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
3902 if (ret)
3903 bytesNeeded += size;
3905 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3906 bytesNeeded += 1 + lenBytes;
3907 if (ret)
3909 if (!pbEncoded)
3910 *pcbEncoded = bytesNeeded;
3911 else
3913 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3914 pbEncoded, pcbEncoded, bytesNeeded)))
3916 BYTE *out;
3918 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3919 pbEncoded = *(BYTE **)pbEncoded;
3920 out = pbEncoded;
3921 *out++ = ASN_SEQUENCEOF;
3922 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
3923 out += lenBytes;
3924 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3926 size = bytesNeeded;
3927 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3928 usage->rgpszUsageIdentifier[i],
3929 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, out, &size);
3930 if (ret)
3932 out += size;
3933 bytesNeeded -= size;
3936 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
3937 CRYPT_FreeSpace(pEncodePara, pbEncoded);
3942 __EXCEPT_PAGE_FAULT
3944 SetLastError(STATUS_ACCESS_VIOLATION);
3945 ret = FALSE;
3947 __ENDTRY
3948 return ret;
3951 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
3952 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3953 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3955 BOOL ret;
3957 __TRY
3959 const CRL_ISSUING_DIST_POINT *point = pvStructInfo;
3960 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3961 struct AsnConstructedItem constructed = { 0 };
3962 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3963 DWORD cItem = 0, cSwapped = 0;
3965 ret = TRUE;
3966 switch (point->DistPointName.dwDistPointNameChoice)
3968 case CRL_DIST_POINT_NO_NAME:
3969 /* do nothing */
3970 break;
3971 case CRL_DIST_POINT_FULL_NAME:
3972 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3973 swapped[cSwapped].pvStructInfo = &point->DistPointName.FullName;
3974 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3975 constructed.tag = 0;
3976 constructed.pvStructInfo = &swapped[cSwapped];
3977 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3978 items[cItem].pvStructInfo = &constructed;
3979 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3980 cSwapped++;
3981 cItem++;
3982 break;
3983 default:
3984 SetLastError(E_INVALIDARG);
3985 ret = FALSE;
3987 if (ret && point->fOnlyContainsUserCerts)
3989 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3990 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3991 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3992 items[cItem].pvStructInfo = &swapped[cSwapped];
3993 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3994 cSwapped++;
3995 cItem++;
3997 if (ret && point->fOnlyContainsCACerts)
3999 swapped[cSwapped].tag = ASN_CONTEXT | 2;
4000 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
4001 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
4002 items[cItem].pvStructInfo = &swapped[cSwapped];
4003 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4004 cSwapped++;
4005 cItem++;
4007 if (ret && point->OnlySomeReasonFlags.cbData)
4009 swapped[cSwapped].tag = ASN_CONTEXT | 3;
4010 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
4011 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
4012 items[cItem].pvStructInfo = &swapped[cSwapped];
4013 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4014 cSwapped++;
4015 cItem++;
4017 if (ret && point->fIndirectCRL)
4019 swapped[cSwapped].tag = ASN_CONTEXT | 4;
4020 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
4021 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
4022 items[cItem].pvStructInfo = &swapped[cSwapped];
4023 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4024 cSwapped++;
4025 cItem++;
4027 if (ret)
4028 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4029 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4031 __EXCEPT_PAGE_FAULT
4033 SetLastError(STATUS_ACCESS_VIOLATION);
4034 ret = FALSE;
4036 __ENDTRY
4037 return ret;
4040 static BOOL CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType,
4041 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4042 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4044 BOOL ret;
4045 const CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
4046 struct AsnEncodeSequenceItem items[3] = {
4047 { &subtree->Base, CRYPT_AsnEncodeAltNameEntry, 0 },
4048 { 0 }
4050 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4051 DWORD cItem = 1, cSwapped = 0;
4053 if (subtree->dwMinimum)
4055 swapped[cSwapped].tag = ASN_CONTEXT | 0;
4056 swapped[cSwapped].pvStructInfo = &subtree->dwMinimum;
4057 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
4058 items[cItem].pvStructInfo = &swapped[cSwapped];
4059 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4060 cSwapped++;
4061 cItem++;
4063 if (subtree->fMaximum)
4065 swapped[cSwapped].tag = ASN_CONTEXT | 1;
4066 swapped[cSwapped].pvStructInfo = &subtree->dwMaximum;
4067 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
4068 items[cItem].pvStructInfo = &swapped[cSwapped];
4069 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4070 cSwapped++;
4071 cItem++;
4073 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags,
4074 pEncodePara, pbEncoded, pcbEncoded);
4075 return ret;
4078 static BOOL WINAPI CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType,
4079 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4080 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4082 BOOL ret = FALSE;
4083 CRYPT_BLOB_ARRAY permitted = { 0, NULL }, excluded = { 0, NULL };
4085 TRACE("%p\n", pvStructInfo);
4087 __TRY
4089 const CERT_NAME_CONSTRAINTS_INFO *constraints = pvStructInfo;
4090 struct AsnEncodeSequenceItem items[2] = { { 0 } };
4091 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4092 DWORD i, cItem = 0, cSwapped = 0;
4094 ret = TRUE;
4095 if (constraints->cPermittedSubtree)
4097 permitted.rgBlob = CryptMemAlloc(
4098 constraints->cPermittedSubtree * sizeof(CRYPT_DER_BLOB));
4099 if (permitted.rgBlob)
4101 permitted.cBlob = constraints->cPermittedSubtree;
4102 memset(permitted.rgBlob, 0,
4103 permitted.cBlob * sizeof(CRYPT_DER_BLOB));
4104 for (i = 0; ret && i < permitted.cBlob; i++)
4105 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
4106 NULL, &constraints->rgPermittedSubtree[i],
4107 CRYPT_ENCODE_ALLOC_FLAG, NULL,
4108 (BYTE *)&permitted.rgBlob[i].pbData,
4109 &permitted.rgBlob[i].cbData);
4110 if (ret)
4112 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4113 swapped[cSwapped].pvStructInfo = &permitted;
4114 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
4115 items[cItem].pvStructInfo = &swapped[cSwapped];
4116 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4117 cSwapped++;
4118 cItem++;
4121 else
4122 ret = FALSE;
4124 if (constraints->cExcludedSubtree)
4126 excluded.rgBlob = CryptMemAlloc(
4127 constraints->cExcludedSubtree * sizeof(CRYPT_DER_BLOB));
4128 if (excluded.rgBlob)
4130 excluded.cBlob = constraints->cExcludedSubtree;
4131 memset(excluded.rgBlob, 0,
4132 excluded.cBlob * sizeof(CRYPT_DER_BLOB));
4133 for (i = 0; ret && i < excluded.cBlob; i++)
4134 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
4135 NULL, &constraints->rgExcludedSubtree[i],
4136 CRYPT_ENCODE_ALLOC_FLAG, NULL,
4137 (BYTE *)&excluded.rgBlob[i].pbData,
4138 &excluded.rgBlob[i].cbData);
4139 if (ret)
4141 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4142 swapped[cSwapped].pvStructInfo = &excluded;
4143 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
4144 items[cItem].pvStructInfo = &swapped[cSwapped];
4145 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4146 cSwapped++;
4147 cItem++;
4150 else
4151 ret = FALSE;
4153 if (ret)
4154 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4155 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4156 for (i = 0; i < permitted.cBlob; i++)
4157 LocalFree(permitted.rgBlob[i].pbData);
4158 for (i = 0; i < excluded.cBlob; i++)
4159 LocalFree(excluded.rgBlob[i].pbData);
4161 __EXCEPT_PAGE_FAULT
4163 SetLastError(STATUS_ACCESS_VIOLATION);
4165 __ENDTRY
4166 CryptMemFree(permitted.rgBlob);
4167 CryptMemFree(excluded.rgBlob);
4168 TRACE("returning %d\n", ret);
4169 return ret;
4172 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
4173 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
4174 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
4175 DWORD *pcbEncoded)
4177 BOOL ret;
4178 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
4179 struct AsnEncodeSequenceItem items[] = {
4180 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
4181 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
4184 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4185 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4186 return ret;
4189 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
4190 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4191 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4193 BOOL ret = FALSE;
4195 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
4197 SetLastError(E_INVALIDARG);
4198 return FALSE;
4201 __TRY
4203 const CMSG_SIGNER_INFO *info = pvStructInfo;
4205 if (!info->Issuer.cbData)
4206 SetLastError(E_INVALIDARG);
4207 else
4209 struct AsnEncodeSequenceItem items[7] = {
4210 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4211 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
4212 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
4213 0 },
4215 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4216 DWORD cItem = 3, cSwapped = 0;
4218 if (info->AuthAttrs.cAttr)
4220 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4221 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
4222 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4223 items[cItem].pvStructInfo = &swapped[cSwapped];
4224 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4225 cSwapped++;
4226 cItem++;
4228 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
4229 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4230 cItem++;
4231 items[cItem].pvStructInfo = &info->EncryptedHash;
4232 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
4233 cItem++;
4234 if (info->UnauthAttrs.cAttr)
4236 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4237 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
4238 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4239 items[cItem].pvStructInfo = &swapped[cSwapped];
4240 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4241 cSwapped++;
4242 cItem++;
4244 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4245 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4248 __EXCEPT_PAGE_FAULT
4250 SetLastError(STATUS_ACCESS_VIOLATION);
4252 __ENDTRY
4253 return ret;
4256 static BOOL WINAPI CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType,
4257 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4258 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4260 BOOL ret = FALSE;
4262 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
4264 SetLastError(E_INVALIDARG);
4265 return FALSE;
4268 __TRY
4270 const CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
4272 if (info->SignerId.dwIdChoice != CERT_ID_ISSUER_SERIAL_NUMBER &&
4273 info->SignerId.dwIdChoice != CERT_ID_KEY_IDENTIFIER)
4274 SetLastError(E_INVALIDARG);
4275 else if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER &&
4276 !info->SignerId.IssuerSerialNumber.Issuer.cbData)
4277 SetLastError(E_INVALIDARG);
4278 else
4280 struct AsnEncodeSequenceItem items[7] = {
4281 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4283 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
4284 DWORD cItem = 1, cSwapped = 0;
4286 if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
4288 items[cItem].pvStructInfo =
4289 &info->SignerId.IssuerSerialNumber.Issuer;
4290 items[cItem].encodeFunc =
4291 CRYPT_AsnEncodeIssuerSerialNumber;
4292 cItem++;
4294 else
4296 swapped[cSwapped].tag = ASN_CONTEXT | 0;
4297 swapped[cSwapped].pvStructInfo = &info->SignerId.KeyId;
4298 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
4299 items[cItem].pvStructInfo = &swapped[cSwapped];
4300 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4301 cSwapped++;
4302 cItem++;
4304 items[cItem].pvStructInfo = &info->HashAlgorithm;
4305 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4306 cItem++;
4307 if (info->AuthAttrs.cAttr)
4309 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4310 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
4311 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4312 items[cItem].pvStructInfo = &swapped[cSwapped];
4313 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4314 cSwapped++;
4315 cItem++;
4317 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
4318 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4319 cItem++;
4320 items[cItem].pvStructInfo = &info->EncryptedHash;
4321 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
4322 cItem++;
4323 if (info->UnauthAttrs.cAttr)
4325 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4326 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
4327 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4328 items[cItem].pvStructInfo = &swapped[cSwapped];
4329 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4330 cSwapped++;
4331 cItem++;
4333 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4334 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4337 __EXCEPT_PAGE_FAULT
4339 SetLastError(STATUS_ACCESS_VIOLATION);
4341 __ENDTRY
4342 return ret;
4345 BOOL CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
4346 DWORD *pcbData)
4348 struct DERSetDescriptor digestAlgorithmsSet = { signedInfo->cSignerInfo,
4349 signedInfo->rgSignerInfo, sizeof(CMSG_CMS_SIGNER_INFO),
4350 offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm),
4351 CRYPT_AsnEncodeAlgorithmIdWithNullParams };
4352 struct AsnEncodeSequenceItem items[7] = {
4353 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
4354 { &digestAlgorithmsSet, CRYPT_DEREncodeItemsAsSet, 0 },
4355 { &signedInfo->content, CRYPT_AsnEncodePKCSContentInfoInternal, 0 }
4357 struct DERSetDescriptor certSet = { 0 }, crlSet = { 0 }, signerSet = { 0 };
4358 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4359 DWORD cItem = 3, cSwapped = 0;
4361 if (signedInfo->cCertEncoded)
4363 certSet.cItems = signedInfo->cCertEncoded;
4364 certSet.items = signedInfo->rgCertEncoded;
4365 certSet.itemSize = sizeof(CERT_BLOB);
4366 certSet.itemOffset = 0;
4367 certSet.encode = CRYPT_CopyEncodedBlob;
4368 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0;
4369 swapped[cSwapped].pvStructInfo = &certSet;
4370 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4371 items[cItem].pvStructInfo = &swapped[cSwapped];
4372 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4373 cSwapped++;
4374 cItem++;
4376 if (signedInfo->cCrlEncoded)
4378 crlSet.cItems = signedInfo->cCrlEncoded;
4379 crlSet.items = signedInfo->rgCrlEncoded;
4380 crlSet.itemSize = sizeof(CRL_BLOB);
4381 crlSet.itemOffset = 0;
4382 crlSet.encode = CRYPT_CopyEncodedBlob;
4383 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
4384 swapped[cSwapped].pvStructInfo = &crlSet;
4385 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4386 items[cItem].pvStructInfo = &swapped[cSwapped];
4387 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4388 cSwapped++;
4389 cItem++;
4391 signerSet.cItems = signedInfo->cSignerInfo;
4392 signerSet.items = signedInfo->rgSignerInfo;
4393 signerSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
4394 signerSet.itemOffset = 0;
4395 signerSet.encode = CRYPT_AsnEncodeCMSSignerInfo;
4396 items[cItem].pvStructInfo = &signerSet;
4397 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4398 cItem++;
4400 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
4401 items, cItem, 0, NULL, pvData, pcbData);
4404 static BOOL WINAPI CRYPT_AsnEncodeRecipientInfo(DWORD dwCertEncodingType,
4405 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4406 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4408 const CMSG_KEY_TRANS_RECIPIENT_INFO *info = pvStructInfo;
4409 struct AsnEncodeSequenceItem items[] = {
4410 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4411 { &info->RecipientId.IssuerSerialNumber,
4412 CRYPT_AsnEncodeIssuerSerialNumber, 0 },
4413 { &info->KeyEncryptionAlgorithm,
4414 CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
4415 { &info->EncryptedKey, CRYPT_AsnEncodeOctets, 0 },
4418 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4419 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4422 static BOOL WINAPI CRYPT_AsnEncodeEncryptedContentInfo(DWORD dwCertEncodingType,
4423 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4424 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4426 const CRYPT_ENCRYPTED_CONTENT_INFO *info = pvStructInfo;
4427 struct AsnEncodeTagSwappedItem swapped = { ASN_CONTEXT | 0,
4428 &info->encryptedContent, CRYPT_AsnEncodeOctets };
4429 struct AsnEncodeSequenceItem items[] = {
4430 { info->contentType, CRYPT_AsnEncodeOid, 0 },
4431 { &info->contentEncryptionAlgorithm,
4432 CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
4433 { &swapped, CRYPT_AsnEncodeSwapTag, 0 },
4436 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4437 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4440 BOOL CRYPT_AsnEncodePKCSEnvelopedData(const CRYPT_ENVELOPED_DATA *envelopedData,
4441 void *pvData, DWORD *pcbData)
4443 struct DERSetDescriptor recipientInfosSet = { envelopedData->cRecipientInfo,
4444 envelopedData->rgRecipientInfo, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO), 0,
4445 CRYPT_AsnEncodeRecipientInfo };
4446 struct AsnEncodeSequenceItem items[] = {
4447 { &envelopedData->version, CRYPT_AsnEncodeInt, 0 },
4448 { &recipientInfosSet, CRYPT_DEREncodeItemsAsSet, 0 },
4449 { &envelopedData->encryptedContentInfo,
4450 CRYPT_AsnEncodeEncryptedContentInfo, 0 },
4453 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
4454 ARRAY_SIZE(items), 0, NULL, pvData, pcbData);
4457 static BOOL WINAPI CRYPT_AsnEncodeCertId(DWORD dwCertEncodingType,
4458 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4459 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4461 BOOL ret;
4463 __TRY
4465 const OCSP_CERT_ID *id = pvStructInfo;
4466 struct AsnEncodeSequenceItem items[] = {
4467 { &id->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
4468 { &id->IssuerNameHash, CRYPT_AsnEncodeOctets, 0 },
4469 { &id->IssuerKeyHash, CRYPT_AsnEncodeOctets, 0 },
4470 { &id->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
4473 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4474 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4476 __EXCEPT_PAGE_FAULT
4478 SetLastError(STATUS_ACCESS_VIOLATION);
4479 ret = FALSE;
4481 __ENDTRY
4482 return ret;
4485 static BOOL CRYPT_AsnEncodeOCSPRequestEntry(DWORD dwCertEncodingType,
4486 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4487 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4489 BOOL ret;
4491 __TRY
4493 const OCSP_REQUEST_ENTRY *info = pvStructInfo;
4494 struct AsnEncodeSequenceItem items[] = {
4495 { &info->CertId, CRYPT_AsnEncodeCertId, 0 },
4498 if (info->cExtension)
4500 FIXME("extensions not supported\n");
4501 SetLastError(E_INVALIDARG);
4502 ret = FALSE;
4504 else
4506 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4507 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4510 __EXCEPT_PAGE_FAULT
4512 SetLastError(STATUS_ACCESS_VIOLATION);
4513 ret = FALSE;
4515 __ENDTRY
4516 return ret;
4519 struct ocsp_request_list
4521 DWORD count;
4522 OCSP_REQUEST_ENTRY *entry;
4525 static BOOL WINAPI CRYPT_AsnEncodeOCSPRequestEntries(DWORD dwCertEncodingType,
4526 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4527 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4529 BOOL ret;
4531 __TRY
4533 DWORD bytesNeeded, dataLen, lenBytes, i;
4534 const struct ocsp_request_list *list = pvStructInfo;
4536 ret = TRUE;
4537 for (i = 0, dataLen = 0; ret && i < list->count; i++)
4539 DWORD size;
4540 ret = CRYPT_AsnEncodeOCSPRequestEntry(dwCertEncodingType, lpszStructType, &list->entry[i],
4541 dwFlags, pEncodePara, NULL, &size);
4542 if (ret)
4543 dataLen += size;
4545 if (ret)
4547 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
4548 bytesNeeded = 1 + lenBytes + dataLen;
4549 if (!pbEncoded)
4550 *pcbEncoded = bytesNeeded;
4551 else
4553 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
4554 pbEncoded, pcbEncoded, bytesNeeded)))
4556 BYTE *out;
4558 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
4559 pbEncoded = *(BYTE **)pbEncoded;
4560 out = pbEncoded;
4561 *out++ = ASN_SEQUENCEOF;
4562 CRYPT_EncodeLen(dataLen, out, &lenBytes);
4563 out += lenBytes;
4564 for (i = 0; i < list->count; i++)
4566 DWORD size = dataLen;
4568 ret = CRYPT_AsnEncodeOCSPRequestEntry(dwCertEncodingType, lpszStructType,
4569 &list->entry[i], dwFlags, pEncodePara, out, &size);
4570 out += size;
4571 dataLen -= size;
4574 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
4575 CRYPT_FreeSpace(pEncodePara, pbEncoded);
4580 __EXCEPT_PAGE_FAULT
4582 SetLastError(STATUS_ACCESS_VIOLATION);
4583 ret = FALSE;
4585 __ENDTRY
4586 return ret;
4589 static BOOL WINAPI CRYPT_AsnEncodeOCSPRequest(DWORD dwCertEncodingType,
4590 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4591 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4593 BOOL ret;
4595 __TRY
4597 const OCSP_REQUEST_INFO *info = pvStructInfo;
4599 if (info->dwVersion != OCSP_REQUEST_V1)
4601 FIXME("version %lu not supported\n", info->dwVersion);
4602 SetLastError(E_INVALIDARG);
4603 ret = FALSE;
4605 else
4607 if (info->cExtension)
4609 FIXME("extensions not supported\n");
4610 SetLastError(E_INVALIDARG);
4611 ret = FALSE;
4613 else
4615 struct AsnConstructedItem name;
4616 struct AsnEncodeSequenceItem items[2];
4617 DWORD count = 0;
4619 if (info->pRequestorName)
4621 name.tag = 1;
4622 name.pvStructInfo = info->pRequestorName;
4623 name.encodeFunc = CRYPT_AsnEncodeAltNameEntry;
4624 items[count].pvStructInfo = &name;
4625 items[count].encodeFunc = CRYPT_AsnEncodeConstructed;
4626 count++;
4628 if (info->cRequestEntry)
4630 items[count].pvStructInfo = &info->cRequestEntry;
4631 items[count].encodeFunc = CRYPT_AsnEncodeOCSPRequestEntries;
4632 count++;
4635 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4636 count, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4640 __EXCEPT_PAGE_FAULT
4642 SetLastError(STATUS_ACCESS_VIOLATION);
4643 ret = FALSE;
4645 __ENDTRY
4646 return ret;
4649 static BOOL WINAPI CRYPT_AsnEncodeOCSPSignedRequest(DWORD dwCertEncodingType,
4650 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4651 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4653 BOOL ret;
4655 __TRY
4657 const OCSP_SIGNED_REQUEST_INFO *info = pvStructInfo;
4658 struct AsnEncodeSequenceItem items[] = {
4659 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
4662 if (info->pOptionalSignatureInfo) FIXME("pOptionalSignatureInfo not supported\n");
4664 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4665 ARRAY_SIZE(items), dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4667 __EXCEPT_PAGE_FAULT
4669 SetLastError(STATUS_ACCESS_VIOLATION);
4670 ret = FALSE;
4672 __ENDTRY
4673 return ret;
4676 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
4677 LPCSTR lpszStructType)
4679 CryptEncodeObjectExFunc encodeFunc = NULL;
4681 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4682 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4684 SetLastError(ERROR_FILE_NOT_FOUND);
4685 return NULL;
4688 if (IS_INTOID(lpszStructType))
4690 switch (LOWORD(lpszStructType))
4692 case LOWORD(X509_CERT):
4693 encodeFunc = CRYPT_AsnEncodeCert;
4694 break;
4695 case LOWORD(X509_CERT_TO_BE_SIGNED):
4696 encodeFunc = CRYPT_AsnEncodeCertInfo;
4697 break;
4698 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
4699 encodeFunc = CRYPT_AsnEncodeCRLInfo;
4700 break;
4701 case LOWORD(X509_EXTENSIONS):
4702 encodeFunc = CRYPT_AsnEncodeExtensions;
4703 break;
4704 case LOWORD(X509_NAME_VALUE):
4705 encodeFunc = CRYPT_AsnEncodeNameValue;
4706 break;
4707 case LOWORD(X509_NAME):
4708 encodeFunc = CRYPT_AsnEncodeName;
4709 break;
4710 case LOWORD(X509_PUBLIC_KEY_INFO):
4711 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
4712 break;
4713 case LOWORD(X509_AUTHORITY_KEY_ID):
4714 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
4715 break;
4716 case LOWORD(X509_ALTERNATE_NAME):
4717 encodeFunc = CRYPT_AsnEncodeAltName;
4718 break;
4719 case LOWORD(X509_BASIC_CONSTRAINTS):
4720 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
4721 break;
4722 case LOWORD(X509_BASIC_CONSTRAINTS2):
4723 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
4724 break;
4725 case LOWORD(X509_CERT_POLICIES):
4726 encodeFunc = CRYPT_AsnEncodeCertPolicies;
4727 break;
4728 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
4729 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
4730 break;
4731 case LOWORD(X509_UNICODE_NAME):
4732 encodeFunc = CRYPT_AsnEncodeUnicodeName;
4733 break;
4734 case LOWORD(PKCS_CONTENT_INFO):
4735 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
4736 break;
4737 case LOWORD(PKCS_ATTRIBUTE):
4738 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
4739 break;
4740 case LOWORD(X509_UNICODE_NAME_VALUE):
4741 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
4742 break;
4743 case LOWORD(X509_OCTET_STRING):
4744 encodeFunc = CRYPT_AsnEncodeOctets;
4745 break;
4746 case LOWORD(X509_BITS):
4747 case LOWORD(X509_KEY_USAGE):
4748 encodeFunc = CRYPT_AsnEncodeBits;
4749 break;
4750 case LOWORD(X509_INTEGER):
4751 encodeFunc = CRYPT_AsnEncodeInt;
4752 break;
4753 case LOWORD(X509_MULTI_BYTE_INTEGER):
4754 encodeFunc = CRYPT_AsnEncodeInteger;
4755 break;
4756 case LOWORD(X509_MULTI_BYTE_UINT):
4757 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
4758 break;
4759 case LOWORD(X509_ENUMERATED):
4760 encodeFunc = CRYPT_AsnEncodeEnumerated;
4761 break;
4762 case LOWORD(X509_CHOICE_OF_TIME):
4763 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
4764 break;
4765 case LOWORD(X509_AUTHORITY_KEY_ID2):
4766 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
4767 break;
4768 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
4769 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
4770 break;
4771 case LOWORD(X509_SEQUENCE_OF_ANY):
4772 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
4773 break;
4774 case LOWORD(PKCS_UTC_TIME):
4775 encodeFunc = CRYPT_AsnEncodeUtcTime;
4776 break;
4777 case LOWORD(X509_CRL_DIST_POINTS):
4778 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
4779 break;
4780 case LOWORD(X509_ENHANCED_KEY_USAGE):
4781 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
4782 break;
4783 case LOWORD(PKCS_CTL):
4784 encodeFunc = CRYPT_AsnEncodeCTL;
4785 break;
4786 case LOWORD(PKCS_SMIME_CAPABILITIES):
4787 encodeFunc = CRYPT_AsnEncodeSMIMECapabilities;
4788 break;
4789 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
4790 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
4791 break;
4792 case LOWORD(PKCS_ATTRIBUTES):
4793 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4794 break;
4795 case LOWORD(X509_ISSUING_DIST_POINT):
4796 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
4797 break;
4798 case LOWORD(X509_NAME_CONSTRAINTS):
4799 encodeFunc = CRYPT_AsnEncodeNameConstraints;
4800 break;
4801 case LOWORD(X509_POLICY_MAPPINGS):
4802 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
4803 break;
4804 case LOWORD(X509_POLICY_CONSTRAINTS):
4805 encodeFunc = CRYPT_AsnEncodeCertPolicyConstraints;
4806 break;
4807 case LOWORD(PKCS7_SIGNER_INFO):
4808 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
4809 break;
4810 case LOWORD(CMS_SIGNER_INFO):
4811 encodeFunc = CRYPT_AsnEncodeCMSSignerInfo;
4812 break;
4813 case LOWORD(CNG_RSA_PUBLIC_KEY_BLOB):
4814 encodeFunc = CRYPT_AsnEncodeRsaPubKey_Bcrypt;
4815 break;
4816 case LOWORD(OCSP_REQUEST):
4817 encodeFunc = CRYPT_AsnEncodeOCSPRequest;
4818 break;
4819 case LOWORD(OCSP_SIGNED_REQUEST):
4820 encodeFunc = CRYPT_AsnEncodeOCSPSignedRequest;
4821 break;
4822 default:
4823 FIXME("Unimplemented encoder for lpszStructType OID %d\n", LOWORD(lpszStructType));
4826 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4827 encodeFunc = CRYPT_AsnEncodeExtensions;
4828 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4829 encodeFunc = CRYPT_AsnEncodeUtcTime;
4830 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
4831 encodeFunc = CRYPT_AsnEncodeUtcTime;
4832 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4833 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
4834 else if (!strcmp(lpszStructType, szOID_LEGACY_POLICY_MAPPINGS))
4835 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
4836 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4837 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
4838 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4839 encodeFunc = CRYPT_AsnEncodeEnumerated;
4840 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4841 encodeFunc = CRYPT_AsnEncodeBits;
4842 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4843 encodeFunc = CRYPT_AsnEncodeOctets;
4844 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4845 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
4846 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4847 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
4848 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4849 encodeFunc = CRYPT_AsnEncodeAltName;
4850 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4851 encodeFunc = CRYPT_AsnEncodeAltName;
4852 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4853 encodeFunc = CRYPT_AsnEncodeAltName;
4854 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4855 encodeFunc = CRYPT_AsnEncodeAltName;
4856 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4857 encodeFunc = CRYPT_AsnEncodeAltName;
4858 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4859 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
4860 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
4861 encodeFunc = CRYPT_AsnEncodeCertPolicies;
4862 else if (!strcmp(lpszStructType, szOID_POLICY_MAPPINGS))
4863 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
4864 else if (!strcmp(lpszStructType, szOID_POLICY_CONSTRAINTS))
4865 encodeFunc = CRYPT_AsnEncodeCertPolicyConstraints;
4866 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4867 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
4868 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4869 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
4870 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
4871 encodeFunc = CRYPT_AsnEncodeNameConstraints;
4872 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
4873 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
4874 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
4875 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
4876 else if (!strcmp(lpszStructType, szOID_CTL))
4877 encodeFunc = CRYPT_AsnEncodeCTL;
4878 else
4879 FIXME("Unsupported encoder for lpszStructType %s\n", lpszStructType);
4880 return encodeFunc;
4883 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType,
4884 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4886 static HCRYPTOIDFUNCSET set = NULL;
4887 CryptEncodeObjectFunc encodeFunc = NULL;
4889 if (!set)
4890 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
4891 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4892 (void **)&encodeFunc, hFunc);
4893 return encodeFunc;
4896 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType,
4897 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4899 static HCRYPTOIDFUNCSET set = NULL;
4900 CryptEncodeObjectExFunc encodeFunc = NULL;
4902 if (!set)
4903 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
4904 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4905 (void **)&encodeFunc, hFunc);
4906 return encodeFunc;
4909 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4910 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
4912 BOOL ret = FALSE;
4913 HCRYPTOIDFUNCADDR hFunc = NULL;
4914 CryptEncodeObjectFunc pCryptEncodeObject = NULL;
4915 CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL;
4917 TRACE_(crypt)("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType,
4918 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
4919 pcbEncoded);
4921 if (!pbEncoded && !pcbEncoded)
4923 SetLastError(ERROR_INVALID_PARAMETER);
4924 return FALSE;
4927 if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType,
4928 lpszStructType)))
4930 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4931 debugstr_a(lpszStructType));
4932 pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType,
4933 lpszStructType, &hFunc);
4934 if (!pCryptEncodeObject)
4935 pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType,
4936 lpszStructType, &hFunc);
4938 if (pCryptEncodeObject)
4939 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4940 pvStructInfo, pbEncoded, pcbEncoded);
4941 else if (pCryptEncodeObjectEx)
4942 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
4943 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
4944 if (hFunc)
4945 CryptFreeOIDFunctionAddress(hFunc, 0);
4946 TRACE_(crypt)("returning %d\n", ret);
4947 return ret;
4950 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4951 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
4952 void *pvEncoded, DWORD *pcbEncoded)
4954 BOOL ret = FALSE;
4955 HCRYPTOIDFUNCADDR hFunc = NULL;
4956 CryptEncodeObjectExFunc encodeFunc = NULL;
4958 TRACE_(crypt)("(0x%08lx, %s, %p, 0x%08lx, %p, %p, %p)\n", dwCertEncodingType,
4959 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
4960 pvEncoded, pcbEncoded);
4962 if (!pvEncoded && !pcbEncoded)
4964 SetLastError(ERROR_INVALID_PARAMETER);
4965 return FALSE;
4968 SetLastError(NOERROR);
4969 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
4970 if (!pvEncoded) {
4971 SetLastError(ERROR_INVALID_PARAMETER);
4972 return FALSE;
4974 *(BYTE **)pvEncoded = NULL;
4976 encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType);
4977 if (!encodeFunc)
4979 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4980 debugstr_a(lpszStructType));
4981 encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType,
4982 &hFunc);
4984 if (encodeFunc)
4985 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
4986 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
4987 else
4989 CryptEncodeObjectFunc pCryptEncodeObject =
4990 CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4992 if (pCryptEncodeObject)
4994 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
4996 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4997 pvStructInfo, NULL, pcbEncoded);
4998 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
4999 pvEncoded, pcbEncoded, *pcbEncoded)))
5000 ret = pCryptEncodeObject(dwCertEncodingType,
5001 lpszStructType, pvStructInfo, *(BYTE **)pvEncoded,
5002 pcbEncoded);
5004 else
5005 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
5006 pvStructInfo, pvEncoded, pcbEncoded);
5009 if (hFunc)
5010 CryptFreeOIDFunctionAddress(hFunc, 0);
5011 TRACE_(crypt)("returning %d\n", ret);
5012 return ret;
5015 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
5016 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
5018 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
5019 NULL, 0, NULL, pInfo, pcbInfo);
5022 typedef BOOL (WINAPI *EncodePublicKeyAndParametersFunc)(DWORD dwCertEncodingType,
5023 LPSTR pszPublicKeyObjId, BYTE *pbPubKey, DWORD cbPubKey, DWORD dwFlags, void *pvAuxInfo,
5024 BYTE **ppPublicKey, DWORD *pcbPublicKey, BYTE **ppbParams, DWORD *pcbParams);
5026 static BOOL WINAPI CRYPT_ExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
5027 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
5028 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
5030 BOOL ret;
5031 HCRYPTKEY key;
5032 static CHAR rsa_oid[] = szOID_RSA_RSA;
5034 TRACE_(crypt)("(%08Ix, %ld, %08lx, %s, %08lx, %p, %p, %ld)\n", hCryptProv,
5035 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
5036 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
5038 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
5040 DWORD keySize = 0;
5042 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
5043 if (ret)
5045 PUBLICKEYSTRUC *pubKey = CryptMemAlloc(keySize);
5047 if (pubKey)
5049 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, (BYTE *)pubKey, &keySize);
5050 if (ret)
5052 DWORD encodedLen;
5054 if (!pszPublicKeyObjId)
5056 static HCRYPTOIDFUNCSET set;
5057 EncodePublicKeyAndParametersFunc encodeFunc = NULL;
5058 HCRYPTOIDFUNCADDR hFunc = NULL;
5060 pszPublicKeyObjId = (LPSTR)CertAlgIdToOID(pubKey->aiKeyAlg);
5061 TRACE("public key algid %#x (%s)\n", pubKey->aiKeyAlg, debugstr_a(pszPublicKeyObjId));
5063 if (!set) /* FIXME: there is no a public macro */
5064 set = CryptInitOIDFunctionSet("CryptDllEncodePublicKeyAndParameters", 0);
5066 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId, 0, (void **)&encodeFunc, &hFunc);
5067 if (encodeFunc)
5069 BYTE *key_data = NULL;
5070 DWORD key_size = 0;
5071 BYTE *params = NULL;
5072 DWORD params_size = 0;
5074 ret = encodeFunc(dwCertEncodingType, pszPublicKeyObjId, (BYTE *)pubKey, keySize,
5075 dwFlags, pvAuxInfo, &key_data, &key_size, &params, &params_size);
5076 if (ret)
5078 DWORD oid_size = strlen(pszPublicKeyObjId) + 1;
5079 DWORD size_needed = sizeof(*pInfo) + oid_size + key_size + params_size;
5081 if (!pInfo)
5082 *pcbInfo = size_needed;
5083 else if (*pcbInfo < size_needed)
5085 *pcbInfo = size_needed;
5086 SetLastError(ERROR_MORE_DATA);
5087 ret = FALSE;
5089 else
5091 *pcbInfo = size_needed;
5092 pInfo->Algorithm.pszObjId = (char *)(pInfo + 1);
5093 lstrcpyA(pInfo->Algorithm.pszObjId, pszPublicKeyObjId);
5094 if (params)
5096 pInfo->Algorithm.Parameters.cbData = params_size;
5097 pInfo->Algorithm.Parameters.pbData = (BYTE *)pInfo->Algorithm.pszObjId + oid_size;
5098 memcpy(pInfo->Algorithm.Parameters.pbData, params, params_size);
5100 else
5102 pInfo->Algorithm.Parameters.cbData = 0;
5103 pInfo->Algorithm.Parameters.pbData = NULL;
5105 pInfo->PublicKey.pbData = (BYTE *)pInfo->Algorithm.pszObjId + oid_size + params_size;
5106 pInfo->PublicKey.cbData = key_size;
5107 memcpy(pInfo->PublicKey.pbData, key_data, key_size);
5108 pInfo->PublicKey.cUnusedBits = 0;
5111 CryptMemFree(key_data);
5112 CryptMemFree(params);
5115 CryptMemFree(pubKey);
5116 CryptFreeOIDFunctionAddress(hFunc, 0);
5117 return ret;
5120 /* fallback to RSA */
5121 pszPublicKeyObjId = rsa_oid;
5124 encodedLen = 0;
5125 ret = CryptEncodeObject(dwCertEncodingType,
5126 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
5127 if (ret)
5129 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
5130 strlen(pszPublicKeyObjId) + 1 + encodedLen;
5132 if (!pInfo)
5133 *pcbInfo = sizeNeeded;
5134 else if (*pcbInfo < sizeNeeded)
5136 SetLastError(ERROR_MORE_DATA);
5137 *pcbInfo = sizeNeeded;
5138 ret = FALSE;
5140 else
5142 *pcbInfo = sizeNeeded;
5143 pInfo->Algorithm.pszObjId = (char *)pInfo +
5144 sizeof(CERT_PUBLIC_KEY_INFO);
5145 lstrcpyA(pInfo->Algorithm.pszObjId,
5146 pszPublicKeyObjId);
5147 pInfo->Algorithm.Parameters.cbData = 0;
5148 pInfo->Algorithm.Parameters.pbData = NULL;
5149 pInfo->PublicKey.pbData =
5150 (BYTE *)pInfo->Algorithm.pszObjId
5151 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
5152 pInfo->PublicKey.cbData = encodedLen;
5153 pInfo->PublicKey.cUnusedBits = 0;
5154 ret = CryptEncodeObject(dwCertEncodingType,
5155 RSA_CSP_PUBLICKEYBLOB, pubKey,
5156 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
5160 CryptMemFree(pubKey);
5162 else
5163 ret = FALSE;
5165 CryptDestroyKey(key);
5167 return ret;
5170 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
5171 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
5172 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
5174 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
5175 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
5176 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
5178 static HCRYPTOIDFUNCSET set = NULL;
5179 BOOL ret;
5180 ExportPublicKeyInfoExFunc exportFunc = NULL;
5181 HCRYPTOIDFUNCADDR hFunc = NULL;
5183 TRACE_(crypt)("(%08Ix, %ld, %08lx, %s, %08lx, %p, %p, %ld)\n", hCryptProv,
5184 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
5185 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
5187 if (!hCryptProv)
5189 SetLastError(ERROR_INVALID_PARAMETER);
5190 return FALSE;
5193 if (pszPublicKeyObjId)
5195 if (!set)
5196 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
5198 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
5199 0, (void **)&exportFunc, &hFunc);
5201 if (!exportFunc)
5202 exportFunc = CRYPT_ExportPublicKeyInfoEx;
5203 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
5204 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
5205 if (hFunc)
5206 CryptFreeOIDFunctionAddress(hFunc, 0);
5207 return ret;
5210 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
5211 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
5213 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
5214 0, 0, NULL, phKey);
5217 typedef BOOL (WINAPI *ConvertPublicKeyInfoFunc)(DWORD dwCertEncodingType,
5218 PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg, DWORD dwFlags,
5219 BYTE **ppbData, DWORD *dwDataLen);
5221 static BOOL WINAPI CRYPT_ImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
5222 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
5223 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
5225 static HCRYPTOIDFUNCSET set = NULL;
5226 ConvertPublicKeyInfoFunc convertFunc = NULL;
5227 HCRYPTOIDFUNCADDR hFunc = NULL;
5228 BOOL ret;
5229 DWORD pubKeySize;
5230 LPBYTE pubKey;
5232 TRACE_(crypt)("(%08Ix, %08lx, %p, %08x, %08lx, %p, %p)\n", hCryptProv,
5233 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
5235 if (!set)
5236 set = CryptInitOIDFunctionSet(CRYPT_OID_CONVERT_PUBLIC_KEY_INFO_FUNC, 0);
5237 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pInfo->Algorithm.pszObjId,
5238 0, (void **)&convertFunc, &hFunc);
5239 if (convertFunc)
5241 pubKey = NULL;
5242 pubKeySize = 0;
5243 ret = convertFunc(dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, &pubKey, &pubKeySize);
5244 if (ret)
5246 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0, phKey);
5247 CryptMemFree(pubKey);
5250 CryptFreeOIDFunctionAddress(hFunc, 0);
5251 return ret;
5254 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
5255 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
5256 if (ret)
5258 pubKey = CryptMemAlloc(pubKeySize);
5260 if (pubKey)
5262 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
5263 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
5264 &pubKeySize);
5265 if (ret)
5267 if(aiKeyAlg)
5268 ((BLOBHEADER*)pubKey)->aiKeyAlg = aiKeyAlg;
5269 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
5270 phKey);
5272 CryptMemFree(pubKey);
5274 else
5275 ret = FALSE;
5277 return ret;
5280 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
5281 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
5282 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
5284 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
5285 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
5286 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
5288 static HCRYPTOIDFUNCSET set = NULL;
5289 BOOL ret;
5290 ImportPublicKeyInfoExFunc importFunc = NULL;
5291 HCRYPTOIDFUNCADDR hFunc = NULL;
5293 TRACE_(crypt)("(%08Ix, %08lx, %p, %08x, %08lx, %p, %p)\n", hCryptProv,
5294 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
5296 if (!set)
5297 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
5298 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
5299 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
5300 if (!importFunc)
5301 importFunc = CRYPT_ImportPublicKeyInfoEx;
5302 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
5303 pvAuxInfo, phKey);
5304 if (hFunc)
5305 CryptFreeOIDFunctionAddress(hFunc, 0);
5306 return ret;
5309 BOOL WINAPI CryptImportPublicKeyInfoEx2(DWORD dwCertEncodingType,
5310 PCERT_PUBLIC_KEY_INFO pInfo, DWORD dwFlags, void *pvAuxInfo,
5311 BCRYPT_KEY_HANDLE *phKey)
5313 TRACE_(crypt)("(%ld, %p, %08lx, %p, %p)\n", dwCertEncodingType, pInfo,
5314 dwFlags, pvAuxInfo, phKey);
5316 if (dwFlags)
5317 FIXME("flags %#lx ignored\n", dwFlags);
5319 return CNG_ImportPubKey(pInfo, phKey);