push 0e883ac4a03c91e56787e1ec12e001b6558b4b62
[wine/hacks.git] / dlls / crypt32 / encode.c
blobc93539671db306c8c064de3ed8cbcddf329d1c62
1 /*
2 * Copyright 2005-2008 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER encoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface isn't
21 * implemented, so I implement them here.
23 * References:
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
33 #include "config.h"
34 #include "wine/port.h"
36 #include <assert.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <stdlib.h>
41 #define NONAMELESSUNION
43 #include "windef.h"
44 #include "winbase.h"
45 #include "wincrypt.h"
46 #include "snmp.h"
47 #include "wine/debug.h"
48 #include "wine/exception.h"
49 #include "wine/unicode.h"
50 #include "crypt32_private.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
53 WINE_DECLARE_DEBUG_CHANNEL(crypt);
55 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
56 BYTE *, DWORD *);
58 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
59 * The dwCertEncodingType and lpszStructType are ignored by the built-in
60 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
61 * since it must call functions in external DLLs that follow these signatures.
63 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
64 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
65 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
66 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
67 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
68 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
69 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
70 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
71 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
72 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
73 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
74 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
75 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
76 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
77 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
78 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
79 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
80 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
81 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
82 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
83 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
84 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
85 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
86 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
87 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
88 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
89 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
90 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
91 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
92 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
93 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
94 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
95 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
97 BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags, PCRYPT_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 BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
126 DWORD bytesNeeded, significantBytes = 0;
128 if (len <= 0x7f)
129 bytesNeeded = 1;
130 else
132 DWORD temp;
134 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
135 temp <<= 8, significantBytes--)
137 bytesNeeded = significantBytes + 1;
139 if (!pbEncoded)
141 *pcbEncoded = bytesNeeded;
142 return TRUE;
144 if (*pcbEncoded < bytesNeeded)
146 SetLastError(ERROR_MORE_DATA);
147 return FALSE;
149 if (len <= 0x7f)
150 *pbEncoded = (BYTE)len;
151 else
153 DWORD i;
155 *pbEncoded++ = significantBytes | 0x80;
156 for (i = 0; i < significantBytes; i++)
158 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
159 len >>= 8;
162 *pcbEncoded = bytesNeeded;
163 return TRUE;
166 BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
167 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
168 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
170 BOOL ret;
171 DWORD i, dataLen = 0;
173 TRACE("%p, %d, %08x, %p, %p, %d\n", items, cItem, dwFlags, pEncodePara,
174 pbEncoded, *pcbEncoded);
175 for (i = 0, ret = TRUE; ret && i < cItem; i++)
177 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
178 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
179 NULL, &items[i].size);
180 /* Some functions propagate their errors through the size */
181 if (!ret)
182 *pcbEncoded = items[i].size;
183 dataLen += items[i].size;
185 if (ret)
187 DWORD lenBytes, bytesNeeded;
189 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
190 bytesNeeded = 1 + lenBytes + dataLen;
191 if (!pbEncoded)
192 *pcbEncoded = bytesNeeded;
193 else
195 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
196 pcbEncoded, bytesNeeded)))
198 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
199 pbEncoded = *(BYTE **)pbEncoded;
200 *pbEncoded++ = ASN_SEQUENCE;
201 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
202 pbEncoded += lenBytes;
203 for (i = 0; ret && i < cItem; i++)
205 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
206 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
207 NULL, pbEncoded, &items[i].size);
208 /* Some functions propagate their errors through the size */
209 if (!ret)
210 *pcbEncoded = items[i].size;
211 pbEncoded += items[i].size;
216 TRACE("returning %d (%08x)\n", ret, GetLastError());
217 return ret;
220 BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
221 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
222 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
224 BOOL ret;
225 const struct AsnConstructedItem *item =
226 (const struct AsnConstructedItem *)pvStructInfo;
227 DWORD len;
229 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
230 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
232 DWORD dataLen, bytesNeeded;
234 CRYPT_EncodeLen(len, NULL, &dataLen);
235 bytesNeeded = 1 + dataLen + len;
236 if (!pbEncoded)
237 *pcbEncoded = bytesNeeded;
238 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
239 pbEncoded, pcbEncoded, bytesNeeded)))
241 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
242 pbEncoded = *(BYTE **)pbEncoded;
243 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
244 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
245 pbEncoded += dataLen;
246 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
247 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
248 pbEncoded, &len);
249 if (!ret)
251 /* Some functions propagate their errors through the size */
252 *pcbEncoded = len;
256 else
258 /* Some functions propagate their errors through the size */
259 *pcbEncoded = len;
261 return ret;
264 struct AsnEncodeTagSwappedItem
266 BYTE tag;
267 const void *pvStructInfo;
268 CryptEncodeObjectExFunc encodeFunc;
271 /* Sort of a wacky hack, it encodes something using the struct
272 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
273 * given in the struct AsnEncodeTagSwappedItem.
275 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
276 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
277 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
279 BOOL ret;
280 const struct AsnEncodeTagSwappedItem *item =
281 (const struct AsnEncodeTagSwappedItem *)pvStructInfo;
283 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
284 item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
285 if (ret && pbEncoded)
286 *pbEncoded = item->tag;
287 return ret;
290 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
291 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
292 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
294 const DWORD *ver = (const DWORD *)pvStructInfo;
295 BOOL ret;
297 /* CERT_V1 is not encoded */
298 if (*ver == CERT_V1)
300 *pcbEncoded = 0;
301 ret = TRUE;
303 else
305 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
307 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
308 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
310 return ret;
313 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
314 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
315 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
317 const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
318 BOOL ret;
320 if (!pbEncoded)
322 *pcbEncoded = blob->cbData;
323 ret = TRUE;
325 else
327 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
328 pcbEncoded, blob->cbData)))
330 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
331 pbEncoded = *(BYTE **)pbEncoded;
332 if (blob->cbData)
333 memcpy(pbEncoded, blob->pbData, blob->cbData);
334 *pcbEncoded = blob->cbData;
335 ret = TRUE;
338 return ret;
341 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
342 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
343 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
345 BOOL ret;
346 /* This has two filetimes in a row, a NotBefore and a NotAfter */
347 const FILETIME *timePtr = (const FILETIME *)pvStructInfo;
348 struct AsnEncodeSequenceItem items[] = {
349 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
350 { timePtr + 1, CRYPT_AsnEncodeChoiceOfTime, 0 },
353 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
354 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
355 pcbEncoded);
356 return ret;
359 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
360 * if they are empty.
362 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
363 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
364 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
365 DWORD *pcbEncoded)
367 const CRYPT_ALGORITHM_IDENTIFIER *algo =
368 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
369 static const BYTE asn1Null[] = { ASN_NULL, 0 };
370 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
371 (LPBYTE)asn1Null };
372 BOOL ret;
373 struct AsnEncodeSequenceItem items[2] = {
374 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
375 { NULL, CRYPT_CopyEncodedBlob, 0 },
378 if (algo->Parameters.cbData)
379 items[1].pvStructInfo = &algo->Parameters;
380 else
381 items[1].pvStructInfo = &nullBlob;
382 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
383 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
384 pcbEncoded);
385 return ret;
388 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType,
389 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
390 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
392 const CRYPT_ALGORITHM_IDENTIFIER *algo =
393 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
394 BOOL ret;
395 struct AsnEncodeSequenceItem items[] = {
396 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
397 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
400 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
401 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
402 pcbEncoded);
403 return ret;
406 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
407 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
408 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
410 BOOL ret;
412 __TRY
414 const CERT_PUBLIC_KEY_INFO *info =
415 (const CERT_PUBLIC_KEY_INFO *)pvStructInfo;
416 struct AsnEncodeSequenceItem items[] = {
417 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
418 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
421 TRACE("Encoding public key with OID %s\n",
422 debugstr_a(info->Algorithm.pszObjId));
423 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
424 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
425 pcbEncoded);
427 __EXCEPT_PAGE_FAULT
429 SetLastError(STATUS_ACCESS_VIOLATION);
430 ret = FALSE;
432 __ENDTRY
433 return ret;
436 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
437 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
438 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
440 BOOL ret;
442 __TRY
444 const CERT_SIGNED_CONTENT_INFO *info =
445 (const CERT_SIGNED_CONTENT_INFO *)pvStructInfo;
446 struct AsnEncodeSequenceItem items[] = {
447 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
448 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
449 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
452 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
453 items[2].encodeFunc = CRYPT_AsnEncodeBits;
454 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
455 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
456 pcbEncoded);
458 __EXCEPT_PAGE_FAULT
460 SetLastError(STATUS_ACCESS_VIOLATION);
461 ret = FALSE;
463 __ENDTRY
464 return ret;
467 /* Like in Windows, this blithely ignores the validity of the passed-in
468 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
469 * decode properly, see CRYPT_AsnDecodeCertInfo.
471 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
472 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
473 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
475 BOOL ret;
477 __TRY
479 const CERT_INFO *info = (const CERT_INFO *)pvStructInfo;
480 struct AsnEncodeSequenceItem items[10] = {
481 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
482 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
483 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
484 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
485 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
486 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
487 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfo, 0 },
488 { 0 }
490 struct AsnConstructedItem constructed[3] = { { 0 } };
491 DWORD cItem = 7, cConstructed = 0;
493 if (info->IssuerUniqueId.cbData)
495 constructed[cConstructed].tag = 1;
496 constructed[cConstructed].pvStructInfo = &info->IssuerUniqueId;
497 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
498 items[cItem].pvStructInfo = &constructed[cConstructed];
499 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
500 cConstructed++;
501 cItem++;
503 if (info->SubjectUniqueId.cbData)
505 constructed[cConstructed].tag = 2;
506 constructed[cConstructed].pvStructInfo = &info->SubjectUniqueId;
507 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
508 items[cItem].pvStructInfo = &constructed[cConstructed];
509 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
510 cConstructed++;
511 cItem++;
513 if (info->cExtension)
515 constructed[cConstructed].tag = 3;
516 constructed[cConstructed].pvStructInfo = &info->cExtension;
517 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
518 items[cItem].pvStructInfo = &constructed[cConstructed];
519 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
520 cConstructed++;
521 cItem++;
524 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
525 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
527 __EXCEPT_PAGE_FAULT
529 SetLastError(STATUS_ACCESS_VIOLATION);
530 ret = FALSE;
532 __ENDTRY
533 return ret;
536 static BOOL WINAPI CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
537 BYTE *pbEncoded, DWORD *pcbEncoded)
539 struct AsnEncodeSequenceItem items[3] = {
540 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
541 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
542 { 0 }
544 DWORD cItem = 2;
545 BOOL ret;
547 TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded);
549 if (entry->cExtension)
551 items[cItem].pvStructInfo = &entry->cExtension;
552 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
553 cItem++;
556 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
557 pbEncoded, pcbEncoded);
559 TRACE("returning %d (%08x)\n", ret, GetLastError());
560 return ret;
563 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
564 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
565 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
567 DWORD cCRLEntry = *(const DWORD *)pvStructInfo;
568 DWORD bytesNeeded, dataLen, lenBytes, i;
569 const CRL_ENTRY *rgCRLEntry = *(const CRL_ENTRY *const *)
570 ((const BYTE *)pvStructInfo + sizeof(DWORD));
571 BOOL ret = TRUE;
573 for (i = 0, dataLen = 0; ret && i < cCRLEntry; i++)
575 DWORD size;
577 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
578 if (ret)
579 dataLen += size;
581 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
582 bytesNeeded = 1 + lenBytes + dataLen;
583 if (!pbEncoded)
584 *pcbEncoded = bytesNeeded;
585 else
587 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
588 pcbEncoded, bytesNeeded)))
590 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
591 pbEncoded = *(BYTE **)pbEncoded;
592 *pbEncoded++ = ASN_SEQUENCEOF;
593 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
594 pbEncoded += lenBytes;
595 for (i = 0; i < cCRLEntry; i++)
597 DWORD size = dataLen;
599 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], pbEncoded, &size);
600 pbEncoded += size;
601 dataLen -= size;
605 return ret;
608 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
609 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
610 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
612 const DWORD *ver = (const DWORD *)pvStructInfo;
613 BOOL ret;
615 /* CRL_V1 is not encoded */
616 if (*ver == CRL_V1)
618 *pcbEncoded = 0;
619 ret = TRUE;
621 else
622 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
623 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
624 return ret;
627 /* Like in Windows, this blithely ignores the validity of the passed-in
628 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
629 * decode properly, see CRYPT_AsnDecodeCRLInfo.
631 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
632 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
633 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
635 BOOL ret;
637 __TRY
639 const CRL_INFO *info = (const CRL_INFO *)pvStructInfo;
640 struct AsnEncodeSequenceItem items[7] = {
641 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
642 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
643 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
644 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
645 { 0 }
647 struct AsnConstructedItem constructed[1] = { { 0 } };
648 DWORD cItem = 4, cConstructed = 0;
650 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
652 items[cItem].pvStructInfo = &info->NextUpdate;
653 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
654 cItem++;
656 if (info->cCRLEntry)
658 items[cItem].pvStructInfo = &info->cCRLEntry;
659 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
660 cItem++;
662 if (info->cExtension)
664 constructed[cConstructed].tag = 0;
665 constructed[cConstructed].pvStructInfo = &info->cExtension;
666 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
667 items[cItem].pvStructInfo = &constructed[cConstructed];
668 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
669 cConstructed++;
670 cItem++;
673 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
674 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
676 __EXCEPT_PAGE_FAULT
678 SetLastError(STATUS_ACCESS_VIOLATION);
679 ret = FALSE;
681 __ENDTRY
682 return ret;
685 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
686 DWORD *pcbEncoded)
688 BOOL ret;
689 struct AsnEncodeSequenceItem items[3] = {
690 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
691 { NULL, NULL, 0 },
692 { NULL, NULL, 0 },
694 DWORD cItem = 1;
696 TRACE("%p, %p, %d\n", ext, pbEncoded, *pcbEncoded);
698 if (ext->fCritical)
700 items[cItem].pvStructInfo = &ext->fCritical;
701 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
702 cItem++;
704 items[cItem].pvStructInfo = &ext->Value;
705 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
706 cItem++;
708 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
709 pbEncoded, pcbEncoded);
710 TRACE("returning %d (%08x)\n", ret, GetLastError());
711 return ret;
714 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
715 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
716 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
718 BOOL ret;
720 __TRY
722 DWORD bytesNeeded, dataLen, lenBytes, i;
723 const CERT_EXTENSIONS *exts = (const CERT_EXTENSIONS *)pvStructInfo;
725 ret = TRUE;
726 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
728 DWORD size;
730 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
731 if (ret)
732 dataLen += size;
734 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
735 bytesNeeded = 1 + lenBytes + dataLen;
736 if (!pbEncoded)
737 *pcbEncoded = bytesNeeded;
738 else
740 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
741 pcbEncoded, bytesNeeded)))
743 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
744 pbEncoded = *(BYTE **)pbEncoded;
745 *pbEncoded++ = ASN_SEQUENCEOF;
746 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
747 pbEncoded += lenBytes;
748 for (i = 0; i < exts->cExtension; i++)
750 DWORD size = dataLen;
752 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
753 pbEncoded, &size);
754 pbEncoded += size;
755 dataLen -= size;
760 __EXCEPT_PAGE_FAULT
762 SetLastError(STATUS_ACCESS_VIOLATION);
763 ret = FALSE;
765 __ENDTRY
766 return ret;
769 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
770 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
771 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
773 LPCSTR pszObjId = (LPCSTR)pvStructInfo;
774 DWORD bytesNeeded = 0, lenBytes;
775 BOOL ret = TRUE;
776 int firstPos = 0;
777 BYTE firstByte = 0;
779 TRACE("%s\n", debugstr_a(pszObjId));
781 if (pszObjId)
783 const char *ptr;
784 int val1, val2;
786 if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
788 SetLastError(CRYPT_E_ASN1_ERROR);
789 return FALSE;
791 bytesNeeded++;
792 firstByte = val1 * 40 + val2;
793 ptr = pszObjId + firstPos;
794 while (ret && *ptr)
796 int pos;
798 /* note I assume each component is at most 32-bits long in base 2 */
799 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
801 if (val1 >= 0x10000000)
802 bytesNeeded += 5;
803 else if (val1 >= 0x200000)
804 bytesNeeded += 4;
805 else if (val1 >= 0x4000)
806 bytesNeeded += 3;
807 else if (val1 >= 0x80)
808 bytesNeeded += 2;
809 else
810 bytesNeeded += 1;
811 ptr += pos;
812 if (*ptr == '.')
813 ptr++;
815 else
817 SetLastError(CRYPT_E_ASN1_ERROR);
818 return FALSE;
821 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
823 else
824 lenBytes = 1;
825 bytesNeeded += 1 + lenBytes;
826 if (pbEncoded)
828 if (*pcbEncoded < bytesNeeded)
830 SetLastError(ERROR_MORE_DATA);
831 ret = FALSE;
833 else
835 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
836 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
837 pbEncoded += lenBytes;
838 if (pszObjId)
840 const char *ptr;
841 int val, pos;
843 *pbEncoded++ = firstByte;
844 ptr = pszObjId + firstPos;
845 while (ret && *ptr)
847 sscanf(ptr, "%d%n", &val, &pos);
849 unsigned char outBytes[5];
850 int numBytes, i;
852 if (val >= 0x10000000)
853 numBytes = 5;
854 else if (val >= 0x200000)
855 numBytes = 4;
856 else if (val >= 0x4000)
857 numBytes = 3;
858 else if (val >= 0x80)
859 numBytes = 2;
860 else
861 numBytes = 1;
862 for (i = numBytes; i > 0; i--)
864 outBytes[i - 1] = val & 0x7f;
865 val >>= 7;
867 for (i = 0; i < numBytes - 1; i++)
868 *pbEncoded++ = outBytes[i] | 0x80;
869 *pbEncoded++ = outBytes[i];
870 ptr += pos;
871 if (*ptr == '.')
872 ptr++;
878 *pcbEncoded = bytesNeeded;
879 return ret;
882 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
883 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
884 DWORD *pcbEncoded)
886 BOOL ret = TRUE;
887 LPCSTR str = (LPCSTR)value->Value.pbData;
888 DWORD bytesNeeded, lenBytes, encodedLen;
890 encodedLen = value->Value.cbData ? value->Value.cbData : lstrlenA(str);
891 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
892 bytesNeeded = 1 + lenBytes + encodedLen;
893 if (!pbEncoded)
894 *pcbEncoded = bytesNeeded;
895 else
897 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
898 pbEncoded, pcbEncoded, bytesNeeded)))
900 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
901 pbEncoded = *(BYTE **)pbEncoded;
902 *pbEncoded++ = tag;
903 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
904 pbEncoded += lenBytes;
905 memcpy(pbEncoded, str, encodedLen);
908 return ret;
911 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
912 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
913 DWORD *pcbEncoded)
915 BOOL ret = TRUE;
916 LPCWSTR str = (LPCWSTR)value->Value.pbData;
917 DWORD bytesNeeded, lenBytes, strLen;
919 if (value->Value.cbData)
920 strLen = value->Value.cbData / sizeof(WCHAR);
921 else if (value->Value.pbData)
922 strLen = lstrlenW(str);
923 else
924 strLen = 0;
925 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
926 bytesNeeded = 1 + lenBytes + strLen * 2;
927 if (!pbEncoded)
928 *pcbEncoded = bytesNeeded;
929 else
931 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
932 pbEncoded, pcbEncoded, bytesNeeded)))
934 DWORD i;
936 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
937 pbEncoded = *(BYTE **)pbEncoded;
938 *pbEncoded++ = ASN_BMPSTRING;
939 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
940 pbEncoded += lenBytes;
941 for (i = 0; i < strLen; i++)
943 *pbEncoded++ = (str[i] & 0xff00) >> 8;
944 *pbEncoded++ = str[i] & 0x00ff;
948 return ret;
951 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
952 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
953 DWORD *pcbEncoded)
955 BOOL ret = TRUE;
956 LPCWSTR str = (LPCWSTR)value->Value.pbData;
957 DWORD bytesNeeded, lenBytes, encodedLen, strLen;
959 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
960 lstrlenW(str);
961 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
962 NULL);
963 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
964 bytesNeeded = 1 + lenBytes + encodedLen;
965 if (!pbEncoded)
966 *pcbEncoded = bytesNeeded;
967 else
969 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
970 pbEncoded, pcbEncoded, bytesNeeded)))
972 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
973 pbEncoded = *(BYTE **)pbEncoded;
974 *pbEncoded++ = ASN_UTF8STRING;
975 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
976 pbEncoded += lenBytes;
977 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
978 bytesNeeded - lenBytes - 1, NULL, NULL);
981 return ret;
984 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
985 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
986 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
988 BOOL ret = TRUE;
990 __TRY
992 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
994 switch (value->dwValueType)
996 case CERT_RDN_ANY_TYPE:
997 /* explicitly disallowed */
998 SetLastError(E_INVALIDARG);
999 ret = FALSE;
1000 break;
1001 case CERT_RDN_ENCODED_BLOB:
1002 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
1003 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1004 break;
1005 case CERT_RDN_OCTET_STRING:
1006 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1007 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1008 break;
1009 case CERT_RDN_NUMERIC_STRING:
1010 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1011 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1012 break;
1013 case CERT_RDN_PRINTABLE_STRING:
1014 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1015 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1016 break;
1017 case CERT_RDN_TELETEX_STRING:
1018 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1019 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1020 break;
1021 case CERT_RDN_VIDEOTEX_STRING:
1022 ret = CRYPT_AsnEncodeStringCoerce(value,
1023 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1024 break;
1025 case CERT_RDN_IA5_STRING:
1026 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1027 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1028 break;
1029 case CERT_RDN_GRAPHIC_STRING:
1030 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1031 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1032 break;
1033 case CERT_RDN_VISIBLE_STRING:
1034 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1035 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1036 break;
1037 case CERT_RDN_GENERAL_STRING:
1038 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1039 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1040 break;
1041 case CERT_RDN_UNIVERSAL_STRING:
1042 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1043 SetLastError(CRYPT_E_ASN1_CHOICE);
1044 ret = FALSE;
1045 break;
1046 case CERT_RDN_BMP_STRING:
1047 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1048 pbEncoded, pcbEncoded);
1049 break;
1050 case CERT_RDN_UTF8_STRING:
1051 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1052 pbEncoded, pcbEncoded);
1053 break;
1054 default:
1055 SetLastError(CRYPT_E_ASN1_CHOICE);
1056 ret = FALSE;
1059 __EXCEPT_PAGE_FAULT
1061 SetLastError(STATUS_ACCESS_VIOLATION);
1062 ret = FALSE;
1064 __ENDTRY
1065 return ret;
1068 static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1069 CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1070 BYTE *pbEncoded, DWORD *pcbEncoded)
1072 DWORD bytesNeeded = 0, lenBytes, size;
1073 BOOL ret;
1075 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1076 0, NULL, NULL, &size);
1077 if (ret)
1079 bytesNeeded += size;
1080 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1081 * with dwValueType, so "cast" it to get its encoded size
1083 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1084 (CERT_NAME_VALUE *)&attr->dwValueType, 0, NULL, NULL, &size);
1085 if (ret)
1087 bytesNeeded += size;
1088 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1089 bytesNeeded += 1 + lenBytes;
1090 if (pbEncoded)
1092 if (*pcbEncoded < bytesNeeded)
1094 SetLastError(ERROR_MORE_DATA);
1095 ret = FALSE;
1097 else
1099 *pbEncoded++ = ASN_SEQUENCE;
1100 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1101 &lenBytes);
1102 pbEncoded += lenBytes;
1103 size = bytesNeeded - 1 - lenBytes;
1104 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1105 attr->pszObjId, 0, NULL, pbEncoded, &size);
1106 if (ret)
1108 pbEncoded += size;
1109 size = bytesNeeded - 1 - lenBytes - size;
1110 ret = nameValueEncodeFunc(dwCertEncodingType,
1111 NULL, (CERT_NAME_VALUE *)&attr->dwValueType,
1112 0, NULL, pbEncoded, &size);
1113 if (!ret)
1114 *pcbEncoded = size;
1118 if (ret)
1119 *pcbEncoded = bytesNeeded;
1121 else
1123 /* Have to propagate index of failing character */
1124 *pcbEncoded = size;
1127 return ret;
1130 static int BLOBComp(const void *l, const void *r)
1132 const CRYPT_DER_BLOB *a = (const CRYPT_DER_BLOB *)l, *b = (const CRYPT_DER_BLOB *)r;
1133 int ret;
1135 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1136 ret = a->cbData - b->cbData;
1137 return ret;
1140 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1142 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1143 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1144 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1146 const CRYPT_BLOB_ARRAY *set = (const CRYPT_BLOB_ARRAY *)pvStructInfo;
1147 DWORD bytesNeeded = 0, lenBytes, i;
1148 BOOL ret;
1150 for (i = 0; i < set->cBlob; i++)
1151 bytesNeeded += set->rgBlob[i].cbData;
1152 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1153 bytesNeeded += 1 + lenBytes;
1154 if (!pbEncoded)
1156 *pcbEncoded = bytesNeeded;
1157 ret = TRUE;
1159 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1160 pbEncoded, pcbEncoded, bytesNeeded)))
1162 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1163 pbEncoded = *(BYTE **)pbEncoded;
1164 qsort(set->rgBlob, set->cBlob, sizeof(CRYPT_DER_BLOB), BLOBComp);
1165 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1166 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1167 pbEncoded += lenBytes;
1168 for (i = 0; ret && i < set->cBlob; i++)
1170 memcpy(pbEncoded, set->rgBlob[i].pbData, set->rgBlob[i].cbData);
1171 pbEncoded += set->rgBlob[i].cbData;
1174 return ret;
1177 struct DERSetDescriptor
1179 DWORD cItems;
1180 const void *items;
1181 size_t itemSize;
1182 size_t itemOffset;
1183 CryptEncodeObjectExFunc encode;
1186 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,
1187 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1188 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1190 const struct DERSetDescriptor *desc =
1191 (const struct DERSetDescriptor *)pvStructInfo;
1192 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1193 BOOL ret = TRUE;
1194 DWORD i;
1196 if (desc->cItems)
1198 setOf.rgBlob = CryptMemAlloc(desc->cItems * sizeof(CRYPT_DER_BLOB));
1199 if (!setOf.rgBlob)
1200 ret = FALSE;
1201 else
1203 setOf.cBlob = desc->cItems;
1204 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1207 for (i = 0; ret && i < setOf.cBlob; i++)
1209 ret = desc->encode(dwCertEncodingType, lpszStructType,
1210 (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
1211 0, NULL, NULL, &setOf.rgBlob[i].cbData);
1212 if (ret)
1214 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1215 if (!setOf.rgBlob[i].pbData)
1216 ret = FALSE;
1217 else
1218 ret = desc->encode(dwCertEncodingType, lpszStructType,
1219 (const BYTE *)desc->items + i * desc->itemSize +
1220 desc->itemOffset, 0, NULL, setOf.rgBlob[i].pbData,
1221 &setOf.rgBlob[i].cbData);
1223 /* Some functions propagate their errors through the size */
1224 if (!ret)
1225 *pcbEncoded = setOf.rgBlob[i].cbData;
1227 if (ret)
1229 DWORD bytesNeeded = 0, lenBytes;
1231 for (i = 0; i < setOf.cBlob; i++)
1232 bytesNeeded += setOf.rgBlob[i].cbData;
1233 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1234 bytesNeeded += 1 + lenBytes;
1235 if (!pbEncoded)
1236 *pcbEncoded = bytesNeeded;
1237 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1238 pbEncoded, pcbEncoded, bytesNeeded)))
1240 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1241 pbEncoded = *(BYTE **)pbEncoded;
1242 qsort(setOf.rgBlob, setOf.cBlob, sizeof(CRYPT_DER_BLOB),
1243 BLOBComp);
1244 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1245 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1246 pbEncoded += lenBytes;
1247 for (i = 0; i < setOf.cBlob; i++)
1249 memcpy(pbEncoded, setOf.rgBlob[i].pbData,
1250 setOf.rgBlob[i].cbData);
1251 pbEncoded += setOf.rgBlob[i].cbData;
1255 for (i = 0; i < setOf.cBlob; i++)
1256 CryptMemFree(setOf.rgBlob[i].pbData);
1257 CryptMemFree(setOf.rgBlob);
1258 return ret;
1261 static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
1262 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1263 DWORD *pcbEncoded)
1265 BOOL ret;
1266 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1268 __TRY
1270 DWORD i;
1272 ret = TRUE;
1273 if (rdn->cRDNAttr)
1275 setOf.cBlob = rdn->cRDNAttr;
1276 setOf.rgBlob = CryptMemAlloc(rdn->cRDNAttr *
1277 sizeof(CRYPT_DER_BLOB));
1278 if (!setOf.rgBlob)
1279 ret = FALSE;
1280 else
1281 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1283 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1285 setOf.rgBlob[i].cbData = 0;
1286 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1287 nameValueEncodeFunc, NULL, &setOf.rgBlob[i].cbData);
1288 if (ret)
1290 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1291 if (!setOf.rgBlob[i].pbData)
1292 ret = FALSE;
1293 else
1294 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1295 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1296 setOf.rgBlob[i].pbData, &setOf.rgBlob[i].cbData);
1298 if (!ret)
1300 /* Have to propagate index of failing character */
1301 *pcbEncoded = setOf.rgBlob[i].cbData;
1304 if (ret)
1305 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1306 pbEncoded, pcbEncoded);
1307 for (i = 0; i < setOf.cBlob; i++)
1308 CryptMemFree(setOf.rgBlob[i].pbData);
1310 __EXCEPT_PAGE_FAULT
1312 SetLastError(STATUS_ACCESS_VIOLATION);
1313 ret = FALSE;
1315 __ENDTRY
1316 CryptMemFree(setOf.rgBlob);
1317 return ret;
1320 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1321 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1322 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1324 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1325 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1326 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1327 DWORD *pcbEncoded)
1329 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1330 BOOL ret;
1332 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1333 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1334 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1335 else
1336 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1337 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1338 return ret;
1341 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1342 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1343 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1345 BOOL ret = TRUE;
1347 __TRY
1349 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1350 DWORD bytesNeeded = 0, lenBytes, size, i;
1352 TRACE("encoding name with %d RDNs\n", info->cRDN);
1353 ret = TRUE;
1354 for (i = 0; ret && i < info->cRDN; i++)
1356 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1357 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1358 if (ret)
1359 bytesNeeded += size;
1360 else
1361 *pcbEncoded = size;
1363 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1364 bytesNeeded += 1 + lenBytes;
1365 if (ret)
1367 if (!pbEncoded)
1368 *pcbEncoded = bytesNeeded;
1369 else
1371 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1372 pbEncoded, pcbEncoded, bytesNeeded)))
1374 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1375 pbEncoded = *(BYTE **)pbEncoded;
1376 *pbEncoded++ = ASN_SEQUENCEOF;
1377 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1378 &lenBytes);
1379 pbEncoded += lenBytes;
1380 for (i = 0; ret && i < info->cRDN; i++)
1382 size = bytesNeeded;
1383 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1384 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1385 pbEncoded, &size);
1386 if (ret)
1388 pbEncoded += size;
1389 bytesNeeded -= size;
1391 else
1392 *pcbEncoded = size;
1398 __EXCEPT_PAGE_FAULT
1400 SetLastError(STATUS_ACCESS_VIOLATION);
1401 ret = FALSE;
1403 __ENDTRY
1404 return ret;
1407 static BOOL WINAPI CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType,
1408 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1409 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1411 BOOL ret = FALSE;
1413 __TRY
1415 const CRYPT_SMIME_CAPABILITY *capability =
1416 (const CRYPT_SMIME_CAPABILITY *)pvStructInfo;
1418 if (!capability->pszObjId)
1419 SetLastError(E_INVALIDARG);
1420 else
1422 struct AsnEncodeSequenceItem items[] = {
1423 { capability->pszObjId, CRYPT_AsnEncodeOid, 0 },
1424 { &capability->Parameters, CRYPT_CopyEncodedBlob, 0 },
1427 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1428 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1429 pcbEncoded);
1432 __EXCEPT_PAGE_FAULT
1434 SetLastError(STATUS_ACCESS_VIOLATION);
1436 __ENDTRY
1437 return ret;
1440 static BOOL WINAPI CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType,
1441 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1442 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1444 BOOL ret = FALSE;
1446 __TRY
1448 DWORD bytesNeeded, dataLen, lenBytes, i;
1449 const CRYPT_SMIME_CAPABILITIES *capabilities =
1450 (const CRYPT_SMIME_CAPABILITIES *)pvStructInfo;
1452 ret = TRUE;
1453 for (i = 0, dataLen = 0; ret && i < capabilities->cCapability; i++)
1455 DWORD size;
1457 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType, NULL,
1458 &capabilities->rgCapability[i], 0, NULL, NULL, &size);
1459 if (ret)
1460 dataLen += size;
1462 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1463 bytesNeeded = 1 + lenBytes + dataLen;
1464 if (!pbEncoded)
1465 *pcbEncoded = bytesNeeded;
1466 else
1468 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1469 pcbEncoded, bytesNeeded)))
1471 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1472 pbEncoded = *(BYTE **)pbEncoded;
1473 *pbEncoded++ = ASN_SEQUENCEOF;
1474 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1475 pbEncoded += lenBytes;
1476 for (i = 0; i < capabilities->cCapability; i++)
1478 DWORD size = dataLen;
1480 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType,
1481 NULL, &capabilities->rgCapability[i], 0, NULL, pbEncoded,
1482 &size);
1483 pbEncoded += size;
1484 dataLen -= size;
1489 __EXCEPT_PAGE_FAULT
1491 SetLastError(STATUS_ACCESS_VIOLATION);
1493 __ENDTRY
1494 return ret;
1497 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1498 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1499 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1501 BOOL ret = FALSE;
1503 __TRY
1505 const CRYPT_ATTRIBUTE *attr = (const CRYPT_ATTRIBUTE *)pvStructInfo;
1507 if (!attr->pszObjId)
1508 SetLastError(E_INVALIDARG);
1509 else
1511 struct AsnEncodeSequenceItem items[2] = {
1512 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1513 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1516 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1517 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1518 pcbEncoded);
1521 __EXCEPT_PAGE_FAULT
1523 SetLastError(STATUS_ACCESS_VIOLATION);
1525 __ENDTRY
1526 return ret;
1529 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1530 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1531 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1533 BOOL ret = FALSE;
1535 __TRY
1537 const CRYPT_ATTRIBUTES *attributes =
1538 (const CRYPT_ATTRIBUTES *)pvStructInfo;
1539 struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
1540 sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
1542 ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
1543 &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1545 __EXCEPT_PAGE_FAULT
1547 SetLastError(STATUS_ACCESS_VIOLATION);
1549 __ENDTRY
1550 return ret;
1553 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1554 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
1555 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1556 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1557 DWORD *pcbEncoded)
1559 const CRYPT_CONTENT_INFO *info = (const CRYPT_CONTENT_INFO *)pvStructInfo;
1560 struct AsnEncodeSequenceItem items[2] = {
1561 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1562 { NULL, NULL, 0 },
1564 struct AsnConstructedItem constructed = { 0 };
1565 DWORD cItem = 1;
1567 if (info->Content.cbData)
1569 constructed.tag = 0;
1570 constructed.pvStructInfo = &info->Content;
1571 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1572 items[cItem].pvStructInfo = &constructed;
1573 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1574 cItem++;
1576 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1577 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1580 BOOL CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA *digestedData,
1581 void *pvData, DWORD *pcbData)
1583 struct AsnEncodeSequenceItem items[] = {
1584 { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1585 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
1586 0 },
1587 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1588 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1591 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1592 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
1595 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1596 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1597 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1599 BOOL ret = FALSE;
1601 __TRY
1603 const CRYPT_CONTENT_INFO *info =
1604 (const CRYPT_CONTENT_INFO *)pvStructInfo;
1606 if (!info->pszObjId)
1607 SetLastError(E_INVALIDARG);
1608 else
1609 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
1610 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1611 pcbEncoded);
1613 __EXCEPT_PAGE_FAULT
1615 SetLastError(STATUS_ACCESS_VIOLATION);
1617 __ENDTRY
1618 return ret;
1621 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1622 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1623 DWORD *pcbEncoded)
1625 BOOL ret = TRUE;
1626 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1627 DWORD bytesNeeded, lenBytes, encodedLen;
1629 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1630 lstrlenW(str);
1631 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1632 bytesNeeded = 1 + lenBytes + encodedLen;
1633 if (!pbEncoded)
1634 *pcbEncoded = bytesNeeded;
1635 else
1637 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1638 pbEncoded, pcbEncoded, bytesNeeded)))
1640 DWORD i;
1642 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1643 pbEncoded = *(BYTE **)pbEncoded;
1644 *pbEncoded++ = tag;
1645 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1646 pbEncoded += lenBytes;
1647 for (i = 0; i < encodedLen; i++)
1648 *pbEncoded++ = (BYTE)str[i];
1651 return ret;
1654 static void CRYPT_FreeSpace(PCRYPT_ENCODE_PARA pEncodePara, LPVOID pv)
1656 if (pEncodePara && pEncodePara->pfnFree)
1657 pEncodePara->pfnFree(pv);
1658 else
1659 LocalFree(pv);
1662 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
1663 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1664 DWORD *pcbEncoded)
1666 BOOL ret = TRUE;
1667 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1668 DWORD bytesNeeded, lenBytes, encodedLen;
1670 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1671 lstrlenW(str);
1672 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1673 bytesNeeded = 1 + lenBytes + encodedLen;
1674 if (!pbEncoded)
1675 *pcbEncoded = bytesNeeded;
1676 else
1678 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1679 pbEncoded, pcbEncoded, bytesNeeded)))
1681 DWORD i;
1682 BYTE *ptr;
1684 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1685 ptr = *(BYTE **)pbEncoded;
1686 else
1687 ptr = pbEncoded;
1688 *ptr++ = ASN_NUMERICSTRING;
1689 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
1690 ptr += lenBytes;
1691 for (i = 0; ret && i < encodedLen; i++)
1693 if (isdigitW(str[i]))
1694 *ptr++ = (BYTE)str[i];
1695 else
1697 *pcbEncoded = i;
1698 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
1699 ret = FALSE;
1702 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1703 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
1706 return ret;
1709 static inline int isprintableW(WCHAR wc)
1711 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
1712 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
1713 wc == '/' || wc == ':' || wc == '=' || wc == '?';
1716 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
1717 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1718 DWORD *pcbEncoded)
1720 BOOL ret = TRUE;
1721 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1722 DWORD bytesNeeded, lenBytes, encodedLen;
1724 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1725 lstrlenW(str);
1726 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1727 bytesNeeded = 1 + lenBytes + encodedLen;
1728 if (!pbEncoded)
1729 *pcbEncoded = bytesNeeded;
1730 else
1732 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1733 pbEncoded, pcbEncoded, bytesNeeded)))
1735 DWORD i;
1736 BYTE *ptr;
1738 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1739 ptr = *(BYTE **)pbEncoded;
1740 else
1741 ptr = pbEncoded;
1742 *ptr++ = ASN_PRINTABLESTRING;
1743 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
1744 ptr += lenBytes;
1745 for (i = 0; ret && i < encodedLen; i++)
1747 if (isprintableW(str[i]))
1748 *ptr++ = (BYTE)str[i];
1749 else
1751 *pcbEncoded = i;
1752 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
1753 ret = FALSE;
1756 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1757 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
1760 return ret;
1763 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
1764 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1765 DWORD *pcbEncoded)
1767 BOOL ret = TRUE;
1768 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1769 DWORD bytesNeeded, lenBytes, encodedLen;
1771 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1772 lstrlenW(str);
1773 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1774 bytesNeeded = 1 + lenBytes + encodedLen;
1775 if (!pbEncoded)
1776 *pcbEncoded = bytesNeeded;
1777 else
1779 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1780 pbEncoded, pcbEncoded, bytesNeeded)))
1782 DWORD i;
1783 BYTE *ptr;
1785 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1786 ptr = *(BYTE **)pbEncoded;
1787 else
1788 ptr = pbEncoded;
1789 *ptr++ = ASN_IA5STRING;
1790 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
1791 ptr += lenBytes;
1792 for (i = 0; ret && i < encodedLen; i++)
1794 if (str[i] <= 0x7f)
1795 *ptr++ = (BYTE)str[i];
1796 else
1798 *pcbEncoded = i;
1799 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1800 ret = FALSE;
1803 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1804 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
1807 return ret;
1810 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
1811 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1812 DWORD *pcbEncoded)
1814 BOOL ret = TRUE;
1815 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1816 DWORD bytesNeeded, lenBytes, strLen;
1818 /* FIXME: doesn't handle composite characters */
1819 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1820 lstrlenW(str);
1821 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
1822 bytesNeeded = 1 + lenBytes + strLen * 4;
1823 if (!pbEncoded)
1824 *pcbEncoded = bytesNeeded;
1825 else
1827 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1828 pbEncoded, pcbEncoded, bytesNeeded)))
1830 DWORD i;
1832 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1833 pbEncoded = *(BYTE **)pbEncoded;
1834 *pbEncoded++ = ASN_UNIVERSALSTRING;
1835 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
1836 pbEncoded += lenBytes;
1837 for (i = 0; i < strLen; i++)
1839 *pbEncoded++ = 0;
1840 *pbEncoded++ = 0;
1841 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
1842 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
1846 return ret;
1849 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1850 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1851 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1853 BOOL ret = FALSE;
1855 __TRY
1857 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1859 switch (value->dwValueType)
1861 case CERT_RDN_ANY_TYPE:
1862 case CERT_RDN_ENCODED_BLOB:
1863 case CERT_RDN_OCTET_STRING:
1864 SetLastError(CRYPT_E_NOT_CHAR_STRING);
1865 break;
1866 case CERT_RDN_NUMERIC_STRING:
1867 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
1868 pbEncoded, pcbEncoded);
1869 break;
1870 case CERT_RDN_PRINTABLE_STRING:
1871 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
1872 pbEncoded, pcbEncoded);
1873 break;
1874 case CERT_RDN_TELETEX_STRING:
1875 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
1876 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1877 break;
1878 case CERT_RDN_VIDEOTEX_STRING:
1879 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
1880 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1881 break;
1882 case CERT_RDN_IA5_STRING:
1883 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
1884 pbEncoded, pcbEncoded);
1885 break;
1886 case CERT_RDN_GRAPHIC_STRING:
1887 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
1888 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1889 break;
1890 case CERT_RDN_VISIBLE_STRING:
1891 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
1892 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1893 break;
1894 case CERT_RDN_GENERAL_STRING:
1895 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
1896 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1897 break;
1898 case CERT_RDN_UNIVERSAL_STRING:
1899 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
1900 pbEncoded, pcbEncoded);
1901 break;
1902 case CERT_RDN_BMP_STRING:
1903 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1904 pbEncoded, pcbEncoded);
1905 break;
1906 case CERT_RDN_UTF8_STRING:
1907 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1908 pbEncoded, pcbEncoded);
1909 break;
1910 default:
1911 SetLastError(CRYPT_E_ASN1_CHOICE);
1914 __EXCEPT_PAGE_FAULT
1916 SetLastError(STATUS_ACCESS_VIOLATION);
1918 __ENDTRY
1919 return ret;
1922 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
1923 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1924 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1926 BOOL ret;
1928 __TRY
1930 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1931 DWORD bytesNeeded = 0, lenBytes, size, i;
1933 TRACE("encoding name with %d RDNs\n", info->cRDN);
1934 ret = TRUE;
1935 for (i = 0; ret && i < info->cRDN; i++)
1937 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1938 CRYPT_AsnEncodeNameValue, NULL, &size);
1939 if (ret)
1940 bytesNeeded += size;
1942 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1943 bytesNeeded += 1 + lenBytes;
1944 if (ret)
1946 if (!pbEncoded)
1947 *pcbEncoded = bytesNeeded;
1948 else
1950 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1951 pbEncoded, pcbEncoded, bytesNeeded)))
1953 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1954 pbEncoded = *(BYTE **)pbEncoded;
1955 *pbEncoded++ = ASN_SEQUENCEOF;
1956 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1957 &lenBytes);
1958 pbEncoded += lenBytes;
1959 for (i = 0; ret && i < info->cRDN; i++)
1961 size = bytesNeeded;
1962 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1963 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, pbEncoded,
1964 &size);
1965 if (ret)
1967 pbEncoded += size;
1968 bytesNeeded -= size;
1975 __EXCEPT_PAGE_FAULT
1977 SetLastError(STATUS_ACCESS_VIOLATION);
1978 ret = FALSE;
1980 __ENDTRY
1981 return ret;
1984 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1985 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1986 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1988 BOOL val = *(const BOOL *)pvStructInfo, ret;
1990 TRACE("%d\n", val);
1992 if (!pbEncoded)
1994 *pcbEncoded = 3;
1995 ret = TRUE;
1997 else if (*pcbEncoded < 3)
1999 *pcbEncoded = 3;
2000 SetLastError(ERROR_MORE_DATA);
2001 ret = FALSE;
2003 else
2005 *pcbEncoded = 3;
2006 *pbEncoded++ = ASN_BOOL;
2007 *pbEncoded++ = 1;
2008 *pbEncoded++ = val ? 0xff : 0;
2009 ret = TRUE;
2011 TRACE("returning %d (%08x)\n", ret, GetLastError());
2012 return ret;
2015 static BOOL WINAPI CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType,
2016 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2017 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2019 const CERT_ALT_NAME_ENTRY *entry =
2020 (const CERT_ALT_NAME_ENTRY *)pvStructInfo;
2021 BOOL ret;
2022 DWORD dataLen;
2023 BYTE tag;
2025 ret = TRUE;
2026 switch (entry->dwAltNameChoice)
2028 case CERT_ALT_NAME_RFC822_NAME:
2029 case CERT_ALT_NAME_DNS_NAME:
2030 case CERT_ALT_NAME_URL:
2031 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2032 if (entry->u.pwszURL)
2034 DWORD i;
2036 /* Not + 1: don't encode the NULL-terminator */
2037 dataLen = lstrlenW(entry->u.pwszURL);
2038 for (i = 0; ret && i < dataLen; i++)
2040 if (entry->u.pwszURL[i] > 0x7f)
2042 SetLastError(CRYPT_E_INVALID_IA5_STRING);
2043 ret = FALSE;
2044 *pcbEncoded = i;
2048 else
2049 dataLen = 0;
2050 break;
2051 case CERT_ALT_NAME_DIRECTORY_NAME:
2052 tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1);
2053 dataLen = entry->u.DirectoryName.cbData;
2054 break;
2055 case CERT_ALT_NAME_IP_ADDRESS:
2056 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2057 dataLen = entry->u.IPAddress.cbData;
2058 break;
2059 case CERT_ALT_NAME_REGISTERED_ID:
2061 struct AsnEncodeTagSwappedItem swapped =
2062 { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID,
2063 CRYPT_AsnEncodeOid };
2065 return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded,
2066 pcbEncoded);
2068 case CERT_ALT_NAME_OTHER_NAME:
2069 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
2070 return FALSE;
2071 default:
2072 SetLastError(E_INVALIDARG);
2073 return FALSE;
2075 if (ret)
2077 DWORD bytesNeeded, lenBytes;
2079 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2080 bytesNeeded = 1 + dataLen + lenBytes;
2081 if (!pbEncoded)
2082 *pcbEncoded = bytesNeeded;
2083 else if (*pcbEncoded < bytesNeeded)
2085 SetLastError(ERROR_MORE_DATA);
2086 *pcbEncoded = bytesNeeded;
2087 ret = FALSE;
2089 else
2091 *pbEncoded++ = tag;
2092 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2093 pbEncoded += lenBytes;
2094 switch (entry->dwAltNameChoice)
2096 case CERT_ALT_NAME_RFC822_NAME:
2097 case CERT_ALT_NAME_DNS_NAME:
2098 case CERT_ALT_NAME_URL:
2100 DWORD i;
2102 for (i = 0; i < dataLen; i++)
2103 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
2104 break;
2106 case CERT_ALT_NAME_DIRECTORY_NAME:
2107 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen);
2108 break;
2109 case CERT_ALT_NAME_IP_ADDRESS:
2110 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
2111 break;
2113 if (ret)
2114 *pcbEncoded = bytesNeeded;
2117 TRACE("returning %d (%08x)\n", ret, GetLastError());
2118 return ret;
2121 static BOOL WINAPI CRYPT_AsnEncodeIntegerSwapBytes(DWORD dwCertEncodingType,
2122 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2123 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2125 BOOL ret;
2127 __TRY
2129 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2130 CRYPT_DATA_BLOB newBlob = { blob->cbData, NULL };
2132 ret = TRUE;
2133 if (newBlob.cbData)
2135 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2136 if (newBlob.pbData)
2138 DWORD i;
2140 for (i = 0; i < newBlob.cbData; i++)
2141 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2143 else
2144 ret = FALSE;
2146 if (ret)
2147 ret = CRYPT_AsnEncodeInteger(dwCertEncodingType, lpszStructType,
2148 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2149 CryptMemFree(newBlob.pbData);
2151 __EXCEPT_PAGE_FAULT
2153 SetLastError(STATUS_ACCESS_VIOLATION);
2154 ret = FALSE;
2156 __ENDTRY
2157 return ret;
2160 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
2161 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2162 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2164 BOOL ret;
2166 __TRY
2168 const CERT_AUTHORITY_KEY_ID_INFO *info =
2169 (const CERT_AUTHORITY_KEY_ID_INFO *)pvStructInfo;
2170 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2171 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2172 struct AsnConstructedItem constructed = { 0 };
2173 DWORD cItem = 0, cSwapped = 0;
2175 if (info->KeyId.cbData)
2177 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2178 swapped[cSwapped].pvStructInfo = &info->KeyId;
2179 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2180 items[cItem].pvStructInfo = &swapped[cSwapped];
2181 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2182 cSwapped++;
2183 cItem++;
2185 if (info->CertIssuer.cbData)
2187 constructed.tag = 1;
2188 constructed.pvStructInfo = &info->CertIssuer;
2189 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2190 items[cItem].pvStructInfo = &constructed;
2191 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2192 cItem++;
2194 if (info->CertSerialNumber.cbData)
2196 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2197 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2198 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2199 items[cItem].pvStructInfo = &swapped[cSwapped];
2200 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2201 cSwapped++;
2202 cItem++;
2204 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2205 pEncodePara, pbEncoded, pcbEncoded);
2207 __EXCEPT_PAGE_FAULT
2209 SetLastError(STATUS_ACCESS_VIOLATION);
2210 ret = FALSE;
2212 __ENDTRY
2213 return ret;
2216 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2217 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2218 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2220 BOOL ret;
2222 __TRY
2224 const CERT_ALT_NAME_INFO *info =
2225 (const CERT_ALT_NAME_INFO *)pvStructInfo;
2226 DWORD bytesNeeded, dataLen, lenBytes, i;
2228 ret = TRUE;
2229 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2230 * can't encode an erroneous entry index if it's bigger than this.
2232 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2234 DWORD len;
2236 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, NULL,
2237 &info->rgAltEntry[i], 0, NULL, NULL, &len);
2238 if (ret)
2239 dataLen += len;
2240 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2242 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2243 * the bad character, now set the index of the bad
2244 * entry
2246 *pcbEncoded = (BYTE)i <<
2247 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2250 if (ret)
2252 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2253 bytesNeeded = 1 + lenBytes + dataLen;
2254 if (!pbEncoded)
2256 *pcbEncoded = bytesNeeded;
2257 ret = TRUE;
2259 else
2261 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2262 pbEncoded, pcbEncoded, bytesNeeded)))
2264 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2265 pbEncoded = *(BYTE **)pbEncoded;
2266 *pbEncoded++ = ASN_SEQUENCEOF;
2267 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2268 pbEncoded += lenBytes;
2269 for (i = 0; ret && i < info->cAltEntry; i++)
2271 DWORD len = dataLen;
2273 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType,
2274 NULL, &info->rgAltEntry[i], 0, NULL, pbEncoded, &len);
2275 if (ret)
2277 pbEncoded += len;
2278 dataLen -= len;
2285 __EXCEPT_PAGE_FAULT
2287 SetLastError(STATUS_ACCESS_VIOLATION);
2288 ret = FALSE;
2290 __ENDTRY
2291 return ret;
2294 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2295 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2296 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2298 BOOL ret;
2300 __TRY
2302 const CERT_AUTHORITY_KEY_ID2_INFO *info =
2303 (const CERT_AUTHORITY_KEY_ID2_INFO *)pvStructInfo;
2304 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2305 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2306 DWORD cItem = 0, cSwapped = 0;
2308 if (info->KeyId.cbData)
2310 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2311 swapped[cSwapped].pvStructInfo = &info->KeyId;
2312 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2313 items[cItem].pvStructInfo = &swapped[cSwapped];
2314 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2315 cSwapped++;
2316 cItem++;
2318 if (info->AuthorityCertIssuer.cAltEntry)
2320 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2321 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2322 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2323 items[cItem].pvStructInfo = &swapped[cSwapped];
2324 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2325 cSwapped++;
2326 cItem++;
2328 if (info->AuthorityCertSerialNumber.cbData)
2330 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2331 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2332 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2333 items[cItem].pvStructInfo = &swapped[cSwapped];
2334 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2335 cSwapped++;
2336 cItem++;
2338 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2339 pEncodePara, pbEncoded, pcbEncoded);
2341 __EXCEPT_PAGE_FAULT
2343 SetLastError(STATUS_ACCESS_VIOLATION);
2344 ret = FALSE;
2346 __ENDTRY
2347 return ret;
2350 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2351 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2352 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2354 BOOL ret;
2356 __TRY
2358 const CERT_BASIC_CONSTRAINTS_INFO *info =
2359 (const CERT_BASIC_CONSTRAINTS_INFO *)pvStructInfo;
2360 struct AsnEncodeSequenceItem items[3] = {
2361 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2362 { 0 }
2364 DWORD cItem = 1;
2366 if (info->fPathLenConstraint)
2368 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2369 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2370 cItem++;
2372 if (info->cSubtreesConstraint)
2374 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2375 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2376 cItem++;
2378 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2379 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2381 __EXCEPT_PAGE_FAULT
2383 SetLastError(STATUS_ACCESS_VIOLATION);
2384 ret = FALSE;
2386 __ENDTRY
2387 return ret;
2390 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2391 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2392 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2394 BOOL ret;
2396 __TRY
2398 const CERT_BASIC_CONSTRAINTS2_INFO *info =
2399 (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
2400 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2401 DWORD cItem = 0;
2403 if (info->fCA)
2405 items[cItem].pvStructInfo = &info->fCA;
2406 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2407 cItem++;
2409 if (info->fPathLenConstraint)
2411 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2412 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2413 cItem++;
2415 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2416 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2418 __EXCEPT_PAGE_FAULT
2420 SetLastError(STATUS_ACCESS_VIOLATION);
2421 ret = FALSE;
2423 __ENDTRY
2424 return ret;
2427 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
2428 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2429 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2431 BOOL ret;
2433 __TRY
2435 const BLOBHEADER *hdr =
2436 (const BLOBHEADER *)pvStructInfo;
2438 if (hdr->bType != PUBLICKEYBLOB)
2440 SetLastError(E_INVALIDARG);
2441 ret = FALSE;
2443 else
2445 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
2446 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
2447 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
2448 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
2449 struct AsnEncodeSequenceItem items[] = {
2450 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
2451 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
2454 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2455 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
2456 pcbEncoded);
2459 __EXCEPT_PAGE_FAULT
2461 SetLastError(STATUS_ACCESS_VIOLATION);
2462 ret = FALSE;
2464 __ENDTRY
2465 return ret;
2468 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
2469 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2470 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2472 BOOL ret;
2474 __TRY
2476 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2477 DWORD bytesNeeded, lenBytes;
2479 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
2480 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
2482 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
2483 bytesNeeded = 1 + lenBytes + blob->cbData;
2484 if (!pbEncoded)
2486 *pcbEncoded = bytesNeeded;
2487 ret = TRUE;
2489 else
2491 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2492 pcbEncoded, bytesNeeded)))
2494 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2495 pbEncoded = *(BYTE **)pbEncoded;
2496 *pbEncoded++ = ASN_OCTETSTRING;
2497 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
2498 pbEncoded += lenBytes;
2499 if (blob->cbData)
2500 memcpy(pbEncoded, blob->pbData, blob->cbData);
2504 __EXCEPT_PAGE_FAULT
2506 SetLastError(STATUS_ACCESS_VIOLATION);
2507 ret = FALSE;
2509 __ENDTRY
2510 TRACE("returning %d (%08x)\n", ret, GetLastError());
2511 return ret;
2514 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
2515 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2516 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2518 BOOL ret;
2520 __TRY
2522 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2523 DWORD bytesNeeded, lenBytes, dataBytes;
2524 BYTE unusedBits;
2526 /* yep, MS allows cUnusedBits to be >= 8 */
2527 if (!blob->cUnusedBits)
2529 dataBytes = blob->cbData;
2530 unusedBits = 0;
2532 else if (blob->cbData * 8 > blob->cUnusedBits)
2534 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
2535 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
2536 blob->cUnusedBits;
2538 else
2540 dataBytes = 0;
2541 unusedBits = 0;
2543 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
2544 bytesNeeded = 1 + lenBytes + dataBytes + 1;
2545 if (!pbEncoded)
2547 *pcbEncoded = bytesNeeded;
2548 ret = TRUE;
2550 else
2552 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2553 pcbEncoded, bytesNeeded)))
2555 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2556 pbEncoded = *(BYTE **)pbEncoded;
2557 *pbEncoded++ = ASN_BITSTRING;
2558 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
2559 pbEncoded += lenBytes;
2560 *pbEncoded++ = unusedBits;
2561 if (dataBytes)
2563 BYTE mask = 0xff << unusedBits;
2565 if (dataBytes > 1)
2567 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
2568 pbEncoded += dataBytes - 1;
2570 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
2575 __EXCEPT_PAGE_FAULT
2577 SetLastError(STATUS_ACCESS_VIOLATION);
2578 ret = FALSE;
2580 __ENDTRY
2581 return ret;
2584 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
2585 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2586 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2588 BOOL ret;
2590 __TRY
2592 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2593 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
2595 ret = TRUE;
2596 if (newBlob.cbData)
2598 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2599 if (newBlob.pbData)
2601 DWORD i;
2603 for (i = 0; i < newBlob.cbData; i++)
2604 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2606 else
2607 ret = FALSE;
2609 if (ret)
2610 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
2611 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2612 CryptMemFree(newBlob.pbData);
2614 __EXCEPT_PAGE_FAULT
2616 SetLastError(STATUS_ACCESS_VIOLATION);
2617 ret = FALSE;
2619 __ENDTRY
2620 return ret;
2623 BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
2624 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2625 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2627 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
2629 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
2630 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2633 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
2634 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2635 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2637 BOOL ret;
2639 __TRY
2641 DWORD significantBytes, lenBytes, bytesNeeded;
2642 BYTE padByte = 0;
2643 BOOL pad = FALSE;
2644 const CRYPT_INTEGER_BLOB *blob =
2645 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2647 significantBytes = blob->cbData;
2648 if (significantBytes)
2650 if (blob->pbData[significantBytes - 1] & 0x80)
2652 /* negative, lop off leading (little-endian) 0xffs */
2653 for (; significantBytes > 0 &&
2654 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
2656 if (blob->pbData[significantBytes - 1] < 0x80)
2658 padByte = 0xff;
2659 pad = TRUE;
2662 else
2664 /* positive, lop off leading (little-endian) zeroes */
2665 for (; significantBytes > 0 &&
2666 !blob->pbData[significantBytes - 1]; significantBytes--)
2668 if (significantBytes == 0)
2669 significantBytes = 1;
2670 if (blob->pbData[significantBytes - 1] > 0x7f)
2672 padByte = 0;
2673 pad = TRUE;
2677 if (pad)
2678 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2679 else
2680 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2681 bytesNeeded = 1 + lenBytes + significantBytes;
2682 if (pad)
2683 bytesNeeded++;
2684 if (!pbEncoded)
2686 *pcbEncoded = bytesNeeded;
2687 ret = TRUE;
2689 else
2691 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2692 pcbEncoded, bytesNeeded)))
2694 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2695 pbEncoded = *(BYTE **)pbEncoded;
2696 *pbEncoded++ = ASN_INTEGER;
2697 if (pad)
2699 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2700 pbEncoded += lenBytes;
2701 *pbEncoded++ = padByte;
2703 else
2705 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2706 pbEncoded += lenBytes;
2708 for (; significantBytes > 0; significantBytes--)
2709 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2713 __EXCEPT_PAGE_FAULT
2715 SetLastError(STATUS_ACCESS_VIOLATION);
2716 ret = FALSE;
2718 __ENDTRY
2719 return ret;
2722 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
2723 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2724 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2726 BOOL ret;
2728 __TRY
2730 DWORD significantBytes, lenBytes, bytesNeeded;
2731 BOOL pad = FALSE;
2732 const CRYPT_INTEGER_BLOB *blob =
2733 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2735 significantBytes = blob->cbData;
2736 if (significantBytes)
2738 /* positive, lop off leading (little-endian) zeroes */
2739 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
2740 significantBytes--)
2742 if (significantBytes == 0)
2743 significantBytes = 1;
2744 if (blob->pbData[significantBytes - 1] > 0x7f)
2745 pad = TRUE;
2747 if (pad)
2748 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2749 else
2750 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2751 bytesNeeded = 1 + lenBytes + significantBytes;
2752 if (pad)
2753 bytesNeeded++;
2754 if (!pbEncoded)
2756 *pcbEncoded = bytesNeeded;
2757 ret = TRUE;
2759 else
2761 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2762 pcbEncoded, bytesNeeded)))
2764 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2765 pbEncoded = *(BYTE **)pbEncoded;
2766 *pbEncoded++ = ASN_INTEGER;
2767 if (pad)
2769 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2770 pbEncoded += lenBytes;
2771 *pbEncoded++ = 0;
2773 else
2775 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2776 pbEncoded += lenBytes;
2778 for (; significantBytes > 0; significantBytes--)
2779 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2783 __EXCEPT_PAGE_FAULT
2785 SetLastError(STATUS_ACCESS_VIOLATION);
2786 ret = FALSE;
2788 __ENDTRY
2789 return ret;
2792 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
2793 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2794 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2796 CRYPT_INTEGER_BLOB blob;
2797 BOOL ret;
2799 /* Encode as an unsigned integer, then change the tag to enumerated */
2800 blob.cbData = sizeof(DWORD);
2801 blob.pbData = (BYTE *)pvStructInfo;
2802 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
2803 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2804 if (ret && pbEncoded)
2806 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2807 pbEncoded = *(BYTE **)pbEncoded;
2808 pbEncoded[0] = ASN_ENUMERATED;
2810 return ret;
2813 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
2814 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2815 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2817 BOOL ret;
2819 __TRY
2821 SYSTEMTIME sysTime;
2822 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2823 * temporary buffer because the output buffer is not NULL-terminated.
2825 char buf[16];
2826 static const DWORD bytesNeeded = sizeof(buf) - 1;
2828 if (!pbEncoded)
2830 *pcbEncoded = bytesNeeded;
2831 ret = TRUE;
2833 else
2835 /* Sanity check the year, this is a two-digit year format */
2836 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2837 &sysTime);
2838 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
2840 SetLastError(CRYPT_E_BAD_ENCODE);
2841 ret = FALSE;
2843 if (ret)
2845 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2846 pbEncoded, pcbEncoded, bytesNeeded)))
2848 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2849 pbEncoded = *(BYTE **)pbEncoded;
2850 buf[0] = ASN_UTCTIME;
2851 buf[1] = bytesNeeded - 2;
2852 snprintf(buf + 2, sizeof(buf) - 2,
2853 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
2854 sysTime.wYear - 2000 : sysTime.wYear - 1900,
2855 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2856 sysTime.wMinute, sysTime.wSecond);
2857 memcpy(pbEncoded, buf, bytesNeeded);
2862 __EXCEPT_PAGE_FAULT
2864 SetLastError(STATUS_ACCESS_VIOLATION);
2865 ret = FALSE;
2867 __ENDTRY
2868 return ret;
2871 static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
2872 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2873 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2875 BOOL ret;
2877 __TRY
2879 SYSTEMTIME sysTime;
2880 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2881 * temporary buffer because the output buffer is not NULL-terminated.
2883 char buf[18];
2884 static const DWORD bytesNeeded = sizeof(buf) - 1;
2886 if (!pbEncoded)
2888 *pcbEncoded = bytesNeeded;
2889 ret = TRUE;
2891 else
2893 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2894 &sysTime);
2895 if (ret)
2896 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2897 pcbEncoded, bytesNeeded);
2898 if (ret)
2900 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2901 pbEncoded = *(BYTE **)pbEncoded;
2902 buf[0] = ASN_GENERALTIME;
2903 buf[1] = bytesNeeded - 2;
2904 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
2905 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2906 sysTime.wMinute, sysTime.wSecond);
2907 memcpy(pbEncoded, buf, bytesNeeded);
2911 __EXCEPT_PAGE_FAULT
2913 SetLastError(STATUS_ACCESS_VIOLATION);
2914 ret = FALSE;
2916 __ENDTRY
2917 return ret;
2920 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
2921 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2922 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2924 BOOL ret;
2926 __TRY
2928 SYSTEMTIME sysTime;
2930 /* Check the year, if it's in the UTCTime range call that encode func */
2931 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
2932 return FALSE;
2933 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
2934 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
2935 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2936 else
2937 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
2938 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
2939 pcbEncoded);
2941 __EXCEPT_PAGE_FAULT
2943 SetLastError(STATUS_ACCESS_VIOLATION);
2944 ret = FALSE;
2946 __ENDTRY
2947 return ret;
2950 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
2951 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2952 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2954 BOOL ret;
2956 __TRY
2958 DWORD bytesNeeded, dataLen, lenBytes, i;
2959 const CRYPT_SEQUENCE_OF_ANY *seq =
2960 (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2962 for (i = 0, dataLen = 0; i < seq->cValue; i++)
2963 dataLen += seq->rgValue[i].cbData;
2964 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2965 bytesNeeded = 1 + lenBytes + dataLen;
2966 if (!pbEncoded)
2968 *pcbEncoded = bytesNeeded;
2969 ret = TRUE;
2971 else
2973 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2974 pcbEncoded, bytesNeeded)))
2976 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2977 pbEncoded = *(BYTE **)pbEncoded;
2978 *pbEncoded++ = ASN_SEQUENCEOF;
2979 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2980 pbEncoded += lenBytes;
2981 for (i = 0; i < seq->cValue; i++)
2983 memcpy(pbEncoded, seq->rgValue[i].pbData,
2984 seq->rgValue[i].cbData);
2985 pbEncoded += seq->rgValue[i].cbData;
2990 __EXCEPT_PAGE_FAULT
2992 SetLastError(STATUS_ACCESS_VIOLATION);
2993 ret = FALSE;
2995 __ENDTRY
2996 return ret;
2999 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
3000 BYTE *pbEncoded, DWORD *pcbEncoded)
3002 BOOL ret = TRUE;
3003 struct AsnEncodeSequenceItem items[3] = { { 0 } };
3004 struct AsnConstructedItem constructed = { 0 };
3005 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
3006 DWORD cItem = 0, cSwapped = 0;
3008 switch (distPoint->DistPointName.dwDistPointNameChoice)
3010 case CRL_DIST_POINT_NO_NAME:
3011 /* do nothing */
3012 break;
3013 case CRL_DIST_POINT_FULL_NAME:
3014 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3015 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
3016 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3017 constructed.tag = 0;
3018 constructed.pvStructInfo = &swapped[cSwapped];
3019 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3020 items[cItem].pvStructInfo = &constructed;
3021 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3022 cSwapped++;
3023 cItem++;
3024 break;
3025 case CRL_DIST_POINT_ISSUER_RDN_NAME:
3026 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3027 ret = FALSE;
3028 break;
3029 default:
3030 ret = FALSE;
3032 if (ret && distPoint->ReasonFlags.cbData)
3034 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3035 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
3036 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3037 items[cItem].pvStructInfo = &swapped[cSwapped];
3038 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3039 cSwapped++;
3040 cItem++;
3042 if (ret && distPoint->CRLIssuer.cAltEntry)
3044 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
3045 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
3046 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3047 items[cItem].pvStructInfo = &swapped[cSwapped];
3048 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3049 cSwapped++;
3050 cItem++;
3052 if (ret)
3053 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
3054 pbEncoded, pcbEncoded);
3055 return ret;
3058 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
3059 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3060 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3062 BOOL ret;
3064 __TRY
3066 const CRL_DIST_POINTS_INFO *info =
3067 (const CRL_DIST_POINTS_INFO *)pvStructInfo;
3069 if (!info->cDistPoint)
3071 SetLastError(E_INVALIDARG);
3072 ret = FALSE;
3074 else
3076 DWORD bytesNeeded, dataLen, lenBytes, i;
3078 ret = TRUE;
3079 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
3081 DWORD len;
3083 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
3084 &len);
3085 if (ret)
3086 dataLen += len;
3087 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
3089 /* Have to propagate index of failing character */
3090 *pcbEncoded = len;
3093 if (ret)
3095 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3096 bytesNeeded = 1 + lenBytes + dataLen;
3097 if (!pbEncoded)
3099 *pcbEncoded = bytesNeeded;
3100 ret = TRUE;
3102 else
3104 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3105 pbEncoded, pcbEncoded, bytesNeeded)))
3107 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3108 pbEncoded = *(BYTE **)pbEncoded;
3109 *pbEncoded++ = ASN_SEQUENCEOF;
3110 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
3111 pbEncoded += lenBytes;
3112 for (i = 0; ret && i < info->cDistPoint; i++)
3114 DWORD len = dataLen;
3116 ret = CRYPT_AsnEncodeDistPoint(
3117 &info->rgDistPoint[i], pbEncoded, &len);
3118 if (ret)
3120 pbEncoded += len;
3121 dataLen -= len;
3129 __EXCEPT_PAGE_FAULT
3131 SetLastError(STATUS_ACCESS_VIOLATION);
3132 ret = FALSE;
3134 __ENDTRY
3135 return ret;
3138 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3139 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3140 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3142 BOOL ret;
3144 __TRY
3146 const CERT_ENHKEY_USAGE *usage =
3147 (const CERT_ENHKEY_USAGE *)pvStructInfo;
3148 DWORD bytesNeeded = 0, lenBytes, size, i;
3150 ret = TRUE;
3151 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3153 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3154 usage->rgpszUsageIdentifier[i],
3155 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
3156 if (ret)
3157 bytesNeeded += size;
3159 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3160 bytesNeeded += 1 + lenBytes;
3161 if (ret)
3163 if (!pbEncoded)
3164 *pcbEncoded = bytesNeeded;
3165 else
3167 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3168 pbEncoded, pcbEncoded, bytesNeeded)))
3170 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3171 pbEncoded = *(BYTE **)pbEncoded;
3172 *pbEncoded++ = ASN_SEQUENCEOF;
3173 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
3174 &lenBytes);
3175 pbEncoded += lenBytes;
3176 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3178 size = bytesNeeded;
3179 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3180 usage->rgpszUsageIdentifier[i],
3181 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
3182 &size);
3183 if (ret)
3185 pbEncoded += size;
3186 bytesNeeded -= size;
3193 __EXCEPT_PAGE_FAULT
3195 SetLastError(STATUS_ACCESS_VIOLATION);
3196 ret = FALSE;
3198 __ENDTRY
3199 return ret;
3202 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
3203 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3204 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3206 BOOL ret;
3208 __TRY
3210 const CRL_ISSUING_DIST_POINT *point =
3211 (const CRL_ISSUING_DIST_POINT *)pvStructInfo;
3212 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3213 struct AsnConstructedItem constructed = { 0 };
3214 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3215 DWORD cItem = 0, cSwapped = 0;
3217 ret = TRUE;
3218 switch (point->DistPointName.dwDistPointNameChoice)
3220 case CRL_DIST_POINT_NO_NAME:
3221 /* do nothing */
3222 break;
3223 case CRL_DIST_POINT_FULL_NAME:
3224 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3225 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3226 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3227 constructed.tag = 0;
3228 constructed.pvStructInfo = &swapped[cSwapped];
3229 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3230 items[cItem].pvStructInfo = &constructed;
3231 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3232 cSwapped++;
3233 cItem++;
3234 break;
3235 default:
3236 SetLastError(E_INVALIDARG);
3237 ret = FALSE;
3239 if (ret && point->fOnlyContainsUserCerts)
3241 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3242 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3243 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3244 items[cItem].pvStructInfo = &swapped[cSwapped];
3245 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3246 cSwapped++;
3247 cItem++;
3249 if (ret && point->fOnlyContainsCACerts)
3251 swapped[cSwapped].tag = ASN_CONTEXT | 2;
3252 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3253 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3254 items[cItem].pvStructInfo = &swapped[cSwapped];
3255 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3256 cSwapped++;
3257 cItem++;
3259 if (ret && point->OnlySomeReasonFlags.cbData)
3261 swapped[cSwapped].tag = ASN_CONTEXT | 3;
3262 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3263 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3264 items[cItem].pvStructInfo = &swapped[cSwapped];
3265 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3266 cSwapped++;
3267 cItem++;
3269 if (ret && point->fIndirectCRL)
3271 swapped[cSwapped].tag = ASN_CONTEXT | 4;
3272 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
3273 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3274 items[cItem].pvStructInfo = &swapped[cSwapped];
3275 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3276 cSwapped++;
3277 cItem++;
3279 if (ret)
3280 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3281 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3283 __EXCEPT_PAGE_FAULT
3285 SetLastError(STATUS_ACCESS_VIOLATION);
3286 ret = FALSE;
3288 __ENDTRY
3289 return ret;
3292 static BOOL WINAPI CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType,
3293 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3294 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3296 BOOL ret;
3297 const CERT_GENERAL_SUBTREE *subtree =
3298 (const CERT_GENERAL_SUBTREE *)pvStructInfo;
3299 struct AsnEncodeSequenceItem items[3] = {
3300 { &subtree->Base, CRYPT_AsnEncodeAltNameEntry, 0 },
3301 { 0 }
3303 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3304 DWORD cItem = 1, cSwapped = 0;
3306 if (subtree->dwMinimum)
3308 swapped[cSwapped].tag = ASN_CONTEXT | 0;
3309 swapped[cSwapped].pvStructInfo = &subtree->dwMinimum;
3310 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3311 items[cItem].pvStructInfo = &swapped[cSwapped];
3312 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3313 cSwapped++;
3314 cItem++;
3316 if (subtree->fMaximum)
3318 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3319 swapped[cSwapped].pvStructInfo = &subtree->dwMaximum;
3320 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3321 items[cItem].pvStructInfo = &swapped[cSwapped];
3322 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3323 cSwapped++;
3324 cItem++;
3326 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags,
3327 pEncodePara, pbEncoded, pcbEncoded);
3328 return ret;
3331 static BOOL WINAPI CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType,
3332 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3333 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3335 BOOL ret = FALSE;
3336 CRYPT_BLOB_ARRAY permitted = { 0, NULL }, excluded = { 0, NULL };
3338 TRACE("%p\n", pvStructInfo);
3340 __TRY
3342 const CERT_NAME_CONSTRAINTS_INFO *constraints =
3343 (const CERT_NAME_CONSTRAINTS_INFO *)pvStructInfo;
3344 struct AsnEncodeSequenceItem items[2] = { { 0 } };
3345 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3346 DWORD i, cItem = 0, cSwapped = 0;
3348 ret = TRUE;
3349 if (constraints->cPermittedSubtree)
3351 permitted.rgBlob = CryptMemAlloc(
3352 constraints->cPermittedSubtree * sizeof(CRYPT_DER_BLOB));
3353 if (permitted.rgBlob)
3355 permitted.cBlob = constraints->cPermittedSubtree;
3356 memset(permitted.rgBlob, 0,
3357 permitted.cBlob * sizeof(CRYPT_DER_BLOB));
3358 for (i = 0; ret && i < permitted.cBlob; i++)
3359 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3360 NULL, &constraints->rgPermittedSubtree[i],
3361 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3362 (BYTE *)&permitted.rgBlob[i].pbData,
3363 &permitted.rgBlob[i].cbData);
3364 if (ret)
3366 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3367 swapped[cSwapped].pvStructInfo = &permitted;
3368 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3369 items[cItem].pvStructInfo = &swapped[cSwapped];
3370 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3371 cSwapped++;
3372 cItem++;
3375 else
3376 ret = FALSE;
3378 if (constraints->cExcludedSubtree)
3380 excluded.rgBlob = CryptMemAlloc(
3381 constraints->cExcludedSubtree * sizeof(CRYPT_DER_BLOB));
3382 if (excluded.rgBlob)
3384 excluded.cBlob = constraints->cExcludedSubtree;
3385 memset(excluded.rgBlob, 0,
3386 excluded.cBlob * sizeof(CRYPT_DER_BLOB));
3387 for (i = 0; ret && i < excluded.cBlob; i++)
3388 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3389 NULL, &constraints->rgExcludedSubtree[i],
3390 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3391 (BYTE *)&excluded.rgBlob[i].pbData,
3392 &excluded.rgBlob[i].cbData);
3393 if (ret)
3395 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
3396 swapped[cSwapped].pvStructInfo = &excluded;
3397 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3398 items[cItem].pvStructInfo = &swapped[cSwapped];
3399 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3400 cSwapped++;
3401 cItem++;
3404 else
3405 ret = FALSE;
3407 if (ret)
3408 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3409 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3410 for (i = 0; i < permitted.cBlob; i++)
3411 LocalFree(permitted.rgBlob[i].pbData);
3412 for (i = 0; i < excluded.cBlob; i++)
3413 LocalFree(excluded.rgBlob[i].pbData);
3415 __EXCEPT_PAGE_FAULT
3417 SetLastError(STATUS_ACCESS_VIOLATION);
3419 __ENDTRY
3420 CryptMemFree(permitted.rgBlob);
3421 CryptMemFree(excluded.rgBlob);
3422 TRACE("returning %d\n", ret);
3423 return ret;
3426 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
3427 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3428 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3429 DWORD *pcbEncoded)
3431 BOOL ret;
3432 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3433 (const CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3434 struct AsnEncodeSequenceItem items[] = {
3435 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
3436 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
3439 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3440 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3441 pcbEncoded);
3442 return ret;
3445 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
3446 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3447 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3449 BOOL ret = FALSE;
3451 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
3453 SetLastError(E_INVALIDARG);
3454 return FALSE;
3457 __TRY
3459 const CMSG_SIGNER_INFO *info = (const CMSG_SIGNER_INFO *)pvStructInfo;
3461 if (!info->Issuer.cbData)
3462 SetLastError(E_INVALIDARG);
3463 else
3465 struct AsnEncodeSequenceItem items[7] = {
3466 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
3467 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
3468 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
3469 0 },
3471 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3472 DWORD cItem = 3, cSwapped = 0;
3474 if (info->AuthAttrs.cAttr)
3476 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3477 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
3478 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3479 items[cItem].pvStructInfo = &swapped[cSwapped];
3480 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3481 cSwapped++;
3482 cItem++;
3484 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
3485 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
3486 cItem++;
3487 items[cItem].pvStructInfo = &info->EncryptedHash;
3488 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
3489 cItem++;
3490 if (info->UnauthAttrs.cAttr)
3492 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
3493 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
3494 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3495 items[cItem].pvStructInfo = &swapped[cSwapped];
3496 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3497 cSwapped++;
3498 cItem++;
3500 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3501 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3504 __EXCEPT_PAGE_FAULT
3506 SetLastError(STATUS_ACCESS_VIOLATION);
3508 __ENDTRY
3509 return ret;
3512 static BOOL WINAPI CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType,
3513 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3514 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3516 BOOL ret = FALSE;
3518 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
3520 SetLastError(E_INVALIDARG);
3521 return FALSE;
3524 __TRY
3526 const CMSG_CMS_SIGNER_INFO *info = (const CMSG_CMS_SIGNER_INFO *)pvStructInfo;
3528 if (info->SignerId.dwIdChoice != CERT_ID_ISSUER_SERIAL_NUMBER &&
3529 info->SignerId.dwIdChoice != CERT_ID_KEY_IDENTIFIER)
3530 SetLastError(E_INVALIDARG);
3531 else if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER &&
3532 !info->SignerId.u.IssuerSerialNumber.Issuer.cbData)
3533 SetLastError(E_INVALIDARG);
3534 else
3536 struct AsnEncodeSequenceItem items[7] = {
3537 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
3539 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
3540 DWORD cItem = 1, cSwapped = 0;
3542 if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
3544 items[cItem].pvStructInfo =
3545 &info->SignerId.u.IssuerSerialNumber.Issuer;
3546 items[cItem].encodeFunc =
3547 CRYPT_AsnEncodeIssuerSerialNumber;
3548 cItem++;
3550 else
3552 swapped[cSwapped].tag = ASN_CONTEXT | 0;
3553 swapped[cSwapped].pvStructInfo = &info->SignerId.u.KeyId;
3554 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
3555 items[cItem].pvStructInfo = &swapped[cSwapped];
3556 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3557 cSwapped++;
3558 cItem++;
3560 items[cItem].pvStructInfo = &info->HashAlgorithm;
3561 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
3562 cItem++;
3563 if (info->AuthAttrs.cAttr)
3565 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3566 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
3567 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3568 items[cItem].pvStructInfo = &swapped[cSwapped];
3569 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3570 cSwapped++;
3571 cItem++;
3573 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
3574 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
3575 cItem++;
3576 items[cItem].pvStructInfo = &info->EncryptedHash;
3577 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
3578 cItem++;
3579 if (info->UnauthAttrs.cAttr)
3581 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
3582 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
3583 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3584 items[cItem].pvStructInfo = &swapped[cSwapped];
3585 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3586 cSwapped++;
3587 cItem++;
3589 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3590 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3593 __EXCEPT_PAGE_FAULT
3595 SetLastError(STATUS_ACCESS_VIOLATION);
3597 __ENDTRY
3598 return ret;
3601 BOOL CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
3602 DWORD *pcbData)
3604 struct AsnEncodeSequenceItem items[7] = {
3605 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
3607 struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 };
3608 struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 };
3609 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3610 DWORD cItem = 1, cSwapped = 0;
3611 BOOL ret = TRUE;
3613 if (signedInfo->cSignerInfo)
3615 digestAlgorithmsSet.cItems = signedInfo->cSignerInfo;
3616 digestAlgorithmsSet.items = signedInfo->rgSignerInfo;
3617 digestAlgorithmsSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
3618 digestAlgorithmsSet.itemOffset =
3619 offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm);
3620 digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
3621 items[cItem].pvStructInfo = &digestAlgorithmsSet;
3622 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3623 cItem++;
3625 items[cItem].pvStructInfo = &signedInfo->content;
3626 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal;
3627 cItem++;
3628 if (signedInfo->cCertEncoded)
3630 certSet.cItems = signedInfo->cCertEncoded;
3631 certSet.items = signedInfo->rgCertEncoded;
3632 certSet.itemSize = sizeof(CERT_BLOB);
3633 certSet.itemOffset = 0;
3634 certSet.encode = CRYPT_CopyEncodedBlob;
3635 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0;
3636 swapped[cSwapped].pvStructInfo = &certSet;
3637 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3638 items[cItem].pvStructInfo = &swapped[cSwapped];
3639 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3640 cSwapped++;
3641 cItem++;
3643 if (signedInfo->cCrlEncoded)
3645 crlSet.cItems = signedInfo->cCrlEncoded;
3646 crlSet.items = signedInfo->rgCrlEncoded;
3647 crlSet.itemSize = sizeof(CRL_BLOB);
3648 crlSet.itemOffset = 0;
3649 crlSet.encode = CRYPT_CopyEncodedBlob;
3650 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
3651 swapped[cSwapped].pvStructInfo = &crlSet;
3652 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3653 items[cItem].pvStructInfo = &swapped[cSwapped];
3654 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3655 cSwapped++;
3656 cItem++;
3658 if (ret && signedInfo->cSignerInfo)
3660 signerSet.cItems = signedInfo->cSignerInfo;
3661 signerSet.items = signedInfo->rgSignerInfo;
3662 signerSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
3663 signerSet.itemOffset = 0;
3664 signerSet.encode = CRYPT_AsnEncodeCMSSignerInfo;
3665 items[cItem].pvStructInfo = &signerSet;
3666 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3667 cItem++;
3669 if (ret)
3670 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
3671 items, cItem, 0, NULL, pvData, pcbData);
3673 return ret;
3676 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
3677 LPCSTR lpszStructType)
3679 CryptEncodeObjectExFunc encodeFunc = NULL;
3681 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3682 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3684 SetLastError(ERROR_FILE_NOT_FOUND);
3685 return NULL;
3688 if (!HIWORD(lpszStructType))
3690 switch (LOWORD(lpszStructType))
3692 case LOWORD(X509_CERT):
3693 encodeFunc = CRYPT_AsnEncodeCert;
3694 break;
3695 case LOWORD(X509_CERT_TO_BE_SIGNED):
3696 encodeFunc = CRYPT_AsnEncodeCertInfo;
3697 break;
3698 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
3699 encodeFunc = CRYPT_AsnEncodeCRLInfo;
3700 break;
3701 case LOWORD(X509_EXTENSIONS):
3702 encodeFunc = CRYPT_AsnEncodeExtensions;
3703 break;
3704 case LOWORD(X509_NAME_VALUE):
3705 encodeFunc = CRYPT_AsnEncodeNameValue;
3706 break;
3707 case LOWORD(X509_NAME):
3708 encodeFunc = CRYPT_AsnEncodeName;
3709 break;
3710 case LOWORD(X509_PUBLIC_KEY_INFO):
3711 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
3712 break;
3713 case LOWORD(X509_AUTHORITY_KEY_ID):
3714 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3715 break;
3716 case LOWORD(X509_ALTERNATE_NAME):
3717 encodeFunc = CRYPT_AsnEncodeAltName;
3718 break;
3719 case LOWORD(X509_BASIC_CONSTRAINTS):
3720 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3721 break;
3722 case LOWORD(X509_BASIC_CONSTRAINTS2):
3723 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3724 break;
3725 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
3726 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
3727 break;
3728 case LOWORD(X509_UNICODE_NAME):
3729 encodeFunc = CRYPT_AsnEncodeUnicodeName;
3730 break;
3731 case LOWORD(PKCS_CONTENT_INFO):
3732 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
3733 break;
3734 case LOWORD(PKCS_ATTRIBUTE):
3735 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
3736 break;
3737 case LOWORD(X509_UNICODE_NAME_VALUE):
3738 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
3739 break;
3740 case LOWORD(X509_OCTET_STRING):
3741 encodeFunc = CRYPT_AsnEncodeOctets;
3742 break;
3743 case LOWORD(X509_BITS):
3744 case LOWORD(X509_KEY_USAGE):
3745 encodeFunc = CRYPT_AsnEncodeBits;
3746 break;
3747 case LOWORD(X509_INTEGER):
3748 encodeFunc = CRYPT_AsnEncodeInt;
3749 break;
3750 case LOWORD(X509_MULTI_BYTE_INTEGER):
3751 encodeFunc = CRYPT_AsnEncodeInteger;
3752 break;
3753 case LOWORD(X509_MULTI_BYTE_UINT):
3754 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
3755 break;
3756 case LOWORD(X509_ENUMERATED):
3757 encodeFunc = CRYPT_AsnEncodeEnumerated;
3758 break;
3759 case LOWORD(X509_CHOICE_OF_TIME):
3760 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
3761 break;
3762 case LOWORD(X509_AUTHORITY_KEY_ID2):
3763 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3764 break;
3765 case LOWORD(X509_SEQUENCE_OF_ANY):
3766 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
3767 break;
3768 case LOWORD(PKCS_UTC_TIME):
3769 encodeFunc = CRYPT_AsnEncodeUtcTime;
3770 break;
3771 case LOWORD(X509_CRL_DIST_POINTS):
3772 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3773 break;
3774 case LOWORD(X509_ENHANCED_KEY_USAGE):
3775 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3776 break;
3777 case LOWORD(PKCS_SMIME_CAPABILITIES):
3778 encodeFunc = CRYPT_AsnEncodeSMIMECapabilities;
3779 break;
3780 case LOWORD(PKCS_ATTRIBUTES):
3781 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3782 break;
3783 case LOWORD(X509_ISSUING_DIST_POINT):
3784 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3785 break;
3786 case LOWORD(X509_NAME_CONSTRAINTS):
3787 encodeFunc = CRYPT_AsnEncodeNameConstraints;
3788 break;
3789 case LOWORD(PKCS7_SIGNER_INFO):
3790 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
3791 break;
3792 case LOWORD(CMS_SIGNER_INFO):
3793 encodeFunc = CRYPT_AsnEncodeCMSSignerInfo;
3794 break;
3797 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3798 encodeFunc = CRYPT_AsnEncodeExtensions;
3799 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3800 encodeFunc = CRYPT_AsnEncodeUtcTime;
3801 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
3802 encodeFunc = CRYPT_AsnEncodeUtcTime;
3803 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
3804 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3805 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
3806 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3807 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3808 encodeFunc = CRYPT_AsnEncodeEnumerated;
3809 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3810 encodeFunc = CRYPT_AsnEncodeBits;
3811 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3812 encodeFunc = CRYPT_AsnEncodeOctets;
3813 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3814 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3815 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3816 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3817 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3818 encodeFunc = CRYPT_AsnEncodeAltName;
3819 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3820 encodeFunc = CRYPT_AsnEncodeAltName;
3821 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3822 encodeFunc = CRYPT_AsnEncodeAltName;
3823 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3824 encodeFunc = CRYPT_AsnEncodeAltName;
3825 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3826 encodeFunc = CRYPT_AsnEncodeAltName;
3827 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3828 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3829 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3830 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3831 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3832 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3833 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
3834 encodeFunc = CRYPT_AsnEncodeNameConstraints;
3835 return encodeFunc;
3838 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType,
3839 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
3841 static HCRYPTOIDFUNCSET set = NULL;
3842 CryptEncodeObjectFunc encodeFunc = NULL;
3844 if (!set)
3845 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
3846 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3847 (void **)&encodeFunc, hFunc);
3848 return encodeFunc;
3851 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType,
3852 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
3854 static HCRYPTOIDFUNCSET set = NULL;
3855 CryptEncodeObjectExFunc encodeFunc = NULL;
3857 if (!set)
3858 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
3859 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3860 (void **)&encodeFunc, hFunc);
3861 return encodeFunc;
3864 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3865 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
3867 BOOL ret = FALSE;
3868 HCRYPTOIDFUNCADDR hFunc = NULL;
3869 CryptEncodeObjectFunc pCryptEncodeObject = NULL;
3870 CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL;
3872 TRACE_(crypt)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
3873 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
3874 pcbEncoded);
3876 if (!pbEncoded && !pcbEncoded)
3878 SetLastError(ERROR_INVALID_PARAMETER);
3879 return FALSE;
3882 if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType,
3883 lpszStructType)))
3885 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
3886 debugstr_a(lpszStructType));
3887 pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType,
3888 lpszStructType, &hFunc);
3889 if (!pCryptEncodeObject)
3890 pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType,
3891 lpszStructType, &hFunc);
3893 if (pCryptEncodeObject)
3894 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3895 pvStructInfo, pbEncoded, pcbEncoded);
3896 else if (pCryptEncodeObjectEx)
3897 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
3898 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
3899 if (hFunc)
3900 CryptFreeOIDFunctionAddress(hFunc, 0);
3901 TRACE_(crypt)("returning %d\n", ret);
3902 return ret;
3905 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3906 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
3907 void *pvEncoded, DWORD *pcbEncoded)
3909 BOOL ret = FALSE;
3910 HCRYPTOIDFUNCADDR hFunc = NULL;
3911 CryptEncodeObjectExFunc encodeFunc = NULL;
3913 TRACE_(crypt)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
3914 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
3915 pvEncoded, pcbEncoded);
3917 if (!pvEncoded && !pcbEncoded)
3919 SetLastError(ERROR_INVALID_PARAMETER);
3920 return FALSE;
3923 SetLastError(NOERROR);
3924 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
3925 *(BYTE **)pvEncoded = NULL;
3926 encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType);
3927 if (!encodeFunc)
3929 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
3930 debugstr_a(lpszStructType));
3931 encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType,
3932 &hFunc);
3934 if (encodeFunc)
3935 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
3936 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
3937 else
3939 CryptEncodeObjectFunc pCryptEncodeObject =
3940 CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
3942 if (pCryptEncodeObject)
3944 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3946 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3947 pvStructInfo, NULL, pcbEncoded);
3948 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3949 pvEncoded, pcbEncoded, *pcbEncoded)))
3950 ret = pCryptEncodeObject(dwCertEncodingType,
3951 lpszStructType, pvStructInfo, *(BYTE **)pvEncoded,
3952 pcbEncoded);
3954 else
3955 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3956 pvStructInfo, pvEncoded, pcbEncoded);
3959 if (hFunc)
3960 CryptFreeOIDFunctionAddress(hFunc, 0);
3961 TRACE_(crypt)("returning %d\n", ret);
3962 return ret;
3965 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
3966 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3968 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
3969 NULL, 0, NULL, pInfo, pcbInfo);
3972 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
3973 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3974 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3976 BOOL ret;
3977 HCRYPTKEY key;
3978 static CHAR oid[] = szOID_RSA_RSA;
3980 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
3981 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
3982 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
3984 if (!pszPublicKeyObjId)
3985 pszPublicKeyObjId = oid;
3986 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
3988 DWORD keySize = 0;
3990 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
3991 if (ret)
3993 LPBYTE pubKey = CryptMemAlloc(keySize);
3995 if (pubKey)
3997 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
3998 &keySize);
3999 if (ret)
4001 DWORD encodedLen = 0;
4003 ret = CryptEncodeObject(dwCertEncodingType,
4004 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
4005 if (ret)
4007 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
4008 strlen(pszPublicKeyObjId) + 1 + encodedLen;
4010 if (!pInfo)
4011 *pcbInfo = sizeNeeded;
4012 else if (*pcbInfo < sizeNeeded)
4014 SetLastError(ERROR_MORE_DATA);
4015 *pcbInfo = sizeNeeded;
4016 ret = FALSE;
4018 else
4020 pInfo->Algorithm.pszObjId = (char *)pInfo +
4021 sizeof(CERT_PUBLIC_KEY_INFO);
4022 lstrcpyA(pInfo->Algorithm.pszObjId,
4023 pszPublicKeyObjId);
4024 pInfo->Algorithm.Parameters.cbData = 0;
4025 pInfo->Algorithm.Parameters.pbData = NULL;
4026 pInfo->PublicKey.pbData =
4027 (BYTE *)pInfo->Algorithm.pszObjId
4028 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
4029 pInfo->PublicKey.cbData = encodedLen;
4030 pInfo->PublicKey.cUnusedBits = 0;
4031 ret = CryptEncodeObject(dwCertEncodingType,
4032 RSA_CSP_PUBLICKEYBLOB, pubKey,
4033 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
4037 CryptMemFree(pubKey);
4039 else
4040 ret = FALSE;
4042 CryptDestroyKey(key);
4044 return ret;
4047 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
4048 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
4049 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
4051 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
4052 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
4053 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4055 static HCRYPTOIDFUNCSET set = NULL;
4056 BOOL ret;
4057 ExportPublicKeyInfoExFunc exportFunc = NULL;
4058 HCRYPTOIDFUNCADDR hFunc = NULL;
4060 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
4061 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
4062 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
4064 if (!hCryptProv)
4066 SetLastError(ERROR_INVALID_PARAMETER);
4067 return FALSE;
4070 if (pszPublicKeyObjId)
4072 if (!set)
4073 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
4075 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
4076 0, (void **)&exportFunc, &hFunc);
4078 if (!exportFunc)
4079 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
4080 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
4081 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
4082 if (hFunc)
4083 CryptFreeOIDFunctionAddress(hFunc, 0);
4084 return ret;
4087 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
4088 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
4090 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
4091 0, 0, NULL, phKey);
4094 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
4095 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4096 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
4098 BOOL ret;
4099 DWORD pubKeySize = 0;
4101 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
4102 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
4104 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
4105 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
4106 if (ret)
4108 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
4110 if (pubKey)
4112 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
4113 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
4114 &pubKeySize);
4115 if (ret)
4117 if(aiKeyAlg)
4118 ((BLOBHEADER*)pubKey)->aiKeyAlg = aiKeyAlg;
4119 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
4120 phKey);
4122 CryptMemFree(pubKey);
4124 else
4125 ret = FALSE;
4127 return ret;
4130 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
4131 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4132 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
4134 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
4135 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4136 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
4138 static HCRYPTOIDFUNCSET set = NULL;
4139 BOOL ret;
4140 ImportPublicKeyInfoExFunc importFunc = NULL;
4141 HCRYPTOIDFUNCADDR hFunc = NULL;
4143 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
4144 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
4146 if (!set)
4147 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
4148 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
4149 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
4150 if (!importFunc)
4151 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
4152 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
4153 pvAuxInfo, phKey);
4154 if (hFunc)
4155 CryptFreeOIDFunctionAddress(hFunc, 0);
4156 return ret;