msvcrt: New implementation of fcvt.
[wine/multimedia.git] / dlls / crypt32 / encode.c
blob1963eb7ae9306af53b2050f330007cf0da227459
1 /*
2 * Copyright 2005-2007 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER encoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface isn't
21 * implemented, so I implement them here.
23 * References:
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
33 #include <assert.h>
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <stdlib.h>
38 #define NONAMELESSUNION
40 #include "windef.h"
41 #include "winbase.h"
42 #include "wincrypt.h"
43 #include "snmp.h"
44 #include "wine/debug.h"
45 #include "wine/exception.h"
46 #include "wine/unicode.h"
47 #include "crypt32_private.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
50 WINE_DECLARE_DEBUG_CHANNEL(crypt);
52 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
53 BYTE *, DWORD *);
55 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
56 * The dwCertEncodingType and lpszStructType are ignored by the built-in
57 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
58 * since it must call functions in external DLLs that follow these signatures.
60 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
61 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
62 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
63 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
64 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
65 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
66 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
67 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
68 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
69 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
70 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
71 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
72 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
73 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
74 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
75 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
76 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
77 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
78 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
79 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
80 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
81 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
82 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
83 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
84 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
85 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
86 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
87 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
88 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
89 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
90 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
91 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
92 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
94 BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
95 BYTE *pbEncoded, DWORD *pcbEncoded, DWORD bytesNeeded)
97 BOOL ret = TRUE;
99 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
101 if (pEncodePara && pEncodePara->pfnAlloc)
102 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
103 else
104 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
105 if (!*(BYTE **)pbEncoded)
106 ret = FALSE;
107 else
108 *pcbEncoded = bytesNeeded;
110 else if (bytesNeeded > *pcbEncoded)
112 *pcbEncoded = bytesNeeded;
113 SetLastError(ERROR_MORE_DATA);
114 ret = FALSE;
116 else
117 *pcbEncoded = bytesNeeded;
118 return ret;
121 BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
123 DWORD bytesNeeded, significantBytes = 0;
125 if (len <= 0x7f)
126 bytesNeeded = 1;
127 else
129 DWORD temp;
131 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
132 temp <<= 8, significantBytes--)
134 bytesNeeded = significantBytes + 1;
136 if (!pbEncoded)
138 *pcbEncoded = bytesNeeded;
139 return TRUE;
141 if (*pcbEncoded < bytesNeeded)
143 SetLastError(ERROR_MORE_DATA);
144 return FALSE;
146 if (len <= 0x7f)
147 *pbEncoded = (BYTE)len;
148 else
150 DWORD i;
152 *pbEncoded++ = significantBytes | 0x80;
153 for (i = 0; i < significantBytes; i++)
155 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
156 len >>= 8;
159 *pcbEncoded = bytesNeeded;
160 return TRUE;
163 BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
164 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
165 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
167 BOOL ret;
168 DWORD i, dataLen = 0;
170 TRACE("%p, %d, %08x, %p, %p, %d\n", items, cItem, dwFlags, pEncodePara,
171 pbEncoded, *pcbEncoded);
172 for (i = 0, ret = TRUE; ret && i < cItem; i++)
174 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
175 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
176 NULL, &items[i].size);
177 /* Some functions propagate their errors through the size */
178 if (!ret)
179 *pcbEncoded = items[i].size;
180 dataLen += items[i].size;
182 if (ret)
184 DWORD lenBytes, bytesNeeded;
186 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
187 bytesNeeded = 1 + lenBytes + dataLen;
188 if (!pbEncoded)
189 *pcbEncoded = bytesNeeded;
190 else
192 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
193 pcbEncoded, bytesNeeded)))
195 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
196 pbEncoded = *(BYTE **)pbEncoded;
197 *pbEncoded++ = ASN_SEQUENCE;
198 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
199 pbEncoded += lenBytes;
200 for (i = 0; ret && i < cItem; i++)
202 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
203 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
204 NULL, pbEncoded, &items[i].size);
205 /* Some functions propagate their errors through the size */
206 if (!ret)
207 *pcbEncoded = items[i].size;
208 pbEncoded += items[i].size;
213 TRACE("returning %d (%08x)\n", ret, GetLastError());
214 return ret;
217 BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
218 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
219 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
221 BOOL ret;
222 const struct AsnConstructedItem *item =
223 (const struct AsnConstructedItem *)pvStructInfo;
224 DWORD len;
226 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
227 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
229 DWORD dataLen, bytesNeeded;
231 CRYPT_EncodeLen(len, NULL, &dataLen);
232 bytesNeeded = 1 + dataLen + len;
233 if (!pbEncoded)
234 *pcbEncoded = bytesNeeded;
235 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
236 pbEncoded, pcbEncoded, bytesNeeded)))
238 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
239 pbEncoded = *(BYTE **)pbEncoded;
240 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
241 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
242 pbEncoded += dataLen;
243 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
244 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
245 pbEncoded, &len);
246 if (!ret)
248 /* Some functions propagate their errors through the size */
249 *pcbEncoded = len;
253 else
255 /* Some functions propagate their errors through the size */
256 *pcbEncoded = len;
258 return ret;
261 struct AsnEncodeTagSwappedItem
263 BYTE tag;
264 const void *pvStructInfo;
265 CryptEncodeObjectExFunc encodeFunc;
268 /* Sort of a wacky hack, it encodes something using the struct
269 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
270 * given in the struct AsnEncodeTagSwappedItem.
272 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
273 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
274 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
276 BOOL ret;
277 const struct AsnEncodeTagSwappedItem *item =
278 (const struct AsnEncodeTagSwappedItem *)pvStructInfo;
280 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
281 item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
282 if (ret && pbEncoded)
283 *pbEncoded = item->tag;
284 return ret;
287 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
288 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
289 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
291 const DWORD *ver = (const DWORD *)pvStructInfo;
292 BOOL ret;
294 /* CERT_V1 is not encoded */
295 if (*ver == CERT_V1)
297 *pcbEncoded = 0;
298 ret = TRUE;
300 else
302 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
304 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
305 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
307 return ret;
310 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
311 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
312 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
314 const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
315 BOOL ret;
317 if (!pbEncoded)
319 *pcbEncoded = blob->cbData;
320 ret = TRUE;
322 else
324 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
325 pcbEncoded, blob->cbData)))
327 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
328 pbEncoded = *(BYTE **)pbEncoded;
329 if (blob->cbData)
330 memcpy(pbEncoded, blob->pbData, blob->cbData);
331 *pcbEncoded = blob->cbData;
332 ret = TRUE;
335 return ret;
338 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
339 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
340 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
342 BOOL ret;
343 /* This has two filetimes in a row, a NotBefore and a NotAfter */
344 const FILETIME *timePtr = (const FILETIME *)pvStructInfo;
345 struct AsnEncodeSequenceItem items[] = {
346 { timePtr++, CRYPT_AsnEncodeChoiceOfTime, 0 },
347 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
350 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
351 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
352 pcbEncoded);
353 return ret;
356 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
357 * if they are empty.
359 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
360 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
361 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
362 DWORD *pcbEncoded)
364 const CRYPT_ALGORITHM_IDENTIFIER *algo =
365 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
366 static const BYTE asn1Null[] = { ASN_NULL, 0 };
367 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
368 (LPBYTE)asn1Null };
369 BOOL ret;
370 struct AsnEncodeSequenceItem items[2] = {
371 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
372 { NULL, CRYPT_CopyEncodedBlob, 0 },
375 if (algo->Parameters.cbData)
376 items[1].pvStructInfo = &algo->Parameters;
377 else
378 items[1].pvStructInfo = &nullBlob;
379 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
380 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
381 pcbEncoded);
382 return ret;
385 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType,
386 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
387 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
389 const CRYPT_ALGORITHM_IDENTIFIER *algo =
390 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
391 BOOL ret;
392 struct AsnEncodeSequenceItem items[] = {
393 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
394 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
397 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
398 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
399 pcbEncoded);
400 return ret;
403 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
404 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
405 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
407 BOOL ret;
409 __TRY
411 const CERT_PUBLIC_KEY_INFO *info =
412 (const CERT_PUBLIC_KEY_INFO *)pvStructInfo;
413 struct AsnEncodeSequenceItem items[] = {
414 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
415 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
418 TRACE("Encoding public key with OID %s\n",
419 debugstr_a(info->Algorithm.pszObjId));
420 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
421 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
422 pcbEncoded);
424 __EXCEPT_PAGE_FAULT
426 SetLastError(STATUS_ACCESS_VIOLATION);
427 ret = FALSE;
429 __ENDTRY
430 return ret;
433 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
434 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
435 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
437 BOOL ret;
439 __TRY
441 const CERT_SIGNED_CONTENT_INFO *info =
442 (const CERT_SIGNED_CONTENT_INFO *)pvStructInfo;
443 struct AsnEncodeSequenceItem items[] = {
444 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
445 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
446 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
449 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
450 items[2].encodeFunc = CRYPT_AsnEncodeBits;
451 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
452 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
453 pcbEncoded);
455 __EXCEPT_PAGE_FAULT
457 SetLastError(STATUS_ACCESS_VIOLATION);
458 ret = FALSE;
460 __ENDTRY
461 return ret;
464 /* Like in Windows, this blithely ignores the validity of the passed-in
465 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
466 * decode properly, see CRYPT_AsnDecodeCertInfo.
468 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
469 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
470 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
472 BOOL ret;
474 __TRY
476 const CERT_INFO *info = (const CERT_INFO *)pvStructInfo;
477 struct AsnEncodeSequenceItem items[10] = {
478 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
479 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
480 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
481 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
482 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
483 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
484 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfo, 0 },
485 { 0 }
487 struct AsnConstructedItem constructed[3] = { { 0 } };
488 DWORD cItem = 7, cConstructed = 0;
490 if (info->IssuerUniqueId.cbData)
492 constructed[cConstructed].tag = 1;
493 constructed[cConstructed].pvStructInfo = &info->IssuerUniqueId;
494 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
495 items[cItem].pvStructInfo = &constructed[cConstructed];
496 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
497 cConstructed++;
498 cItem++;
500 if (info->SubjectUniqueId.cbData)
502 constructed[cConstructed].tag = 2;
503 constructed[cConstructed].pvStructInfo = &info->SubjectUniqueId;
504 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
505 items[cItem].pvStructInfo = &constructed[cConstructed];
506 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
507 cConstructed++;
508 cItem++;
510 if (info->cExtension)
512 constructed[cConstructed].tag = 3;
513 constructed[cConstructed].pvStructInfo = &info->cExtension;
514 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
515 items[cItem].pvStructInfo = &constructed[cConstructed];
516 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
517 cConstructed++;
518 cItem++;
521 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
522 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
524 __EXCEPT_PAGE_FAULT
526 SetLastError(STATUS_ACCESS_VIOLATION);
527 ret = FALSE;
529 __ENDTRY
530 return ret;
533 static BOOL WINAPI CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
534 BYTE *pbEncoded, DWORD *pcbEncoded)
536 struct AsnEncodeSequenceItem items[3] = {
537 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
538 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
539 { 0 }
541 DWORD cItem = 2;
542 BOOL ret;
544 TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded);
546 if (entry->cExtension)
548 items[cItem].pvStructInfo = &entry->cExtension;
549 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
550 cItem++;
553 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
554 pbEncoded, pcbEncoded);
556 TRACE("returning %d (%08x)\n", ret, GetLastError());
557 return ret;
560 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
561 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
562 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
564 DWORD cCRLEntry = *(const DWORD *)pvStructInfo;
565 DWORD bytesNeeded, dataLen, lenBytes, i;
566 const CRL_ENTRY *rgCRLEntry = *(const CRL_ENTRY *const *)
567 ((const BYTE *)pvStructInfo + sizeof(DWORD));
568 BOOL ret = TRUE;
570 for (i = 0, dataLen = 0; ret && i < cCRLEntry; i++)
572 DWORD size;
574 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
575 if (ret)
576 dataLen += size;
578 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
579 bytesNeeded = 1 + lenBytes + dataLen;
580 if (!pbEncoded)
581 *pcbEncoded = bytesNeeded;
582 else
584 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
585 pcbEncoded, bytesNeeded)))
587 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
588 pbEncoded = *(BYTE **)pbEncoded;
589 *pbEncoded++ = ASN_SEQUENCEOF;
590 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
591 pbEncoded += lenBytes;
592 for (i = 0; i < cCRLEntry; i++)
594 DWORD size = dataLen;
596 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], pbEncoded, &size);
597 pbEncoded += size;
598 dataLen -= size;
602 return ret;
605 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
606 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
607 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
609 const DWORD *ver = (const DWORD *)pvStructInfo;
610 BOOL ret;
612 /* CRL_V1 is not encoded */
613 if (*ver == CRL_V1)
615 *pcbEncoded = 0;
616 ret = TRUE;
618 else
619 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
620 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
621 return ret;
624 /* Like in Windows, this blithely ignores the validity of the passed-in
625 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
626 * decode properly, see CRYPT_AsnDecodeCRLInfo.
628 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
629 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
630 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
632 BOOL ret;
634 __TRY
636 const CRL_INFO *info = (const CRL_INFO *)pvStructInfo;
637 struct AsnEncodeSequenceItem items[7] = {
638 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
639 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
640 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
641 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
642 { 0 }
644 struct AsnConstructedItem constructed[1] = { { 0 } };
645 DWORD cItem = 4, cConstructed = 0;
647 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
649 items[cItem].pvStructInfo = &info->NextUpdate;
650 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
651 cItem++;
653 if (info->cCRLEntry)
655 items[cItem].pvStructInfo = &info->cCRLEntry;
656 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
657 cItem++;
659 if (info->cExtension)
661 constructed[cConstructed].tag = 0;
662 constructed[cConstructed].pvStructInfo = &info->cExtension;
663 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
664 items[cItem].pvStructInfo = &constructed[cConstructed];
665 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
666 cConstructed++;
667 cItem++;
670 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
671 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
673 __EXCEPT_PAGE_FAULT
675 SetLastError(STATUS_ACCESS_VIOLATION);
676 ret = FALSE;
678 __ENDTRY
679 return ret;
682 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
683 DWORD *pcbEncoded)
685 BOOL ret;
686 struct AsnEncodeSequenceItem items[3] = {
687 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
688 { NULL, NULL, 0 },
689 { NULL, NULL, 0 },
691 DWORD cItem = 1;
693 TRACE("%p, %p, %d\n", ext, pbEncoded, *pcbEncoded);
695 if (ext->fCritical)
697 items[cItem].pvStructInfo = &ext->fCritical;
698 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
699 cItem++;
701 items[cItem].pvStructInfo = &ext->Value;
702 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
703 cItem++;
705 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
706 pbEncoded, pcbEncoded);
707 TRACE("returning %d (%08x)\n", ret, GetLastError());
708 return ret;
711 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
712 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
713 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
715 BOOL ret;
717 __TRY
719 DWORD bytesNeeded, dataLen, lenBytes, i;
720 const CERT_EXTENSIONS *exts = (const CERT_EXTENSIONS *)pvStructInfo;
722 ret = TRUE;
723 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
725 DWORD size;
727 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
728 if (ret)
729 dataLen += size;
731 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
732 bytesNeeded = 1 + lenBytes + dataLen;
733 if (!pbEncoded)
734 *pcbEncoded = bytesNeeded;
735 else
737 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
738 pcbEncoded, bytesNeeded)))
740 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
741 pbEncoded = *(BYTE **)pbEncoded;
742 *pbEncoded++ = ASN_SEQUENCEOF;
743 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
744 pbEncoded += lenBytes;
745 for (i = 0; i < exts->cExtension; i++)
747 DWORD size = dataLen;
749 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
750 pbEncoded, &size);
751 pbEncoded += size;
752 dataLen -= size;
757 __EXCEPT_PAGE_FAULT
759 SetLastError(STATUS_ACCESS_VIOLATION);
760 ret = FALSE;
762 __ENDTRY
763 return ret;
766 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
767 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
768 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
770 LPCSTR pszObjId = (LPCSTR)pvStructInfo;
771 DWORD bytesNeeded = 0, lenBytes;
772 BOOL ret = TRUE;
773 int firstPos = 0;
774 BYTE firstByte = 0;
776 TRACE("%s\n", debugstr_a(pszObjId));
778 if (pszObjId)
780 const char *ptr;
781 int val1, val2;
783 if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
785 SetLastError(CRYPT_E_ASN1_ERROR);
786 return FALSE;
788 bytesNeeded++;
789 firstByte = val1 * 40 + val2;
790 ptr = pszObjId + firstPos;
791 while (ret && *ptr)
793 int pos;
795 /* note I assume each component is at most 32-bits long in base 2 */
796 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
798 if (val1 >= 0x10000000)
799 bytesNeeded += 5;
800 else if (val1 >= 0x200000)
801 bytesNeeded += 4;
802 else if (val1 >= 0x4000)
803 bytesNeeded += 3;
804 else if (val1 >= 0x80)
805 bytesNeeded += 2;
806 else
807 bytesNeeded += 1;
808 ptr += pos;
809 if (*ptr == '.')
810 ptr++;
812 else
814 SetLastError(CRYPT_E_ASN1_ERROR);
815 return FALSE;
818 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
820 else
821 lenBytes = 1;
822 bytesNeeded += 1 + lenBytes;
823 if (pbEncoded)
825 if (*pcbEncoded < bytesNeeded)
827 SetLastError(ERROR_MORE_DATA);
828 ret = FALSE;
830 else
832 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
833 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
834 pbEncoded += lenBytes;
835 if (pszObjId)
837 const char *ptr;
838 int val, pos;
840 *pbEncoded++ = firstByte;
841 ptr = pszObjId + firstPos;
842 while (ret && *ptr)
844 sscanf(ptr, "%d%n", &val, &pos);
846 unsigned char outBytes[5];
847 int numBytes, i;
849 if (val >= 0x10000000)
850 numBytes = 5;
851 else if (val >= 0x200000)
852 numBytes = 4;
853 else if (val >= 0x4000)
854 numBytes = 3;
855 else if (val >= 0x80)
856 numBytes = 2;
857 else
858 numBytes = 1;
859 for (i = numBytes; i > 0; i--)
861 outBytes[i - 1] = val & 0x7f;
862 val >>= 7;
864 for (i = 0; i < numBytes - 1; i++)
865 *pbEncoded++ = outBytes[i] | 0x80;
866 *pbEncoded++ = outBytes[i];
867 ptr += pos;
868 if (*ptr == '.')
869 ptr++;
875 *pcbEncoded = bytesNeeded;
876 return ret;
879 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
880 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
881 DWORD *pcbEncoded)
883 BOOL ret = TRUE;
884 LPCSTR str = (LPCSTR)value->Value.pbData;
885 DWORD bytesNeeded, lenBytes, encodedLen;
887 encodedLen = value->Value.cbData ? value->Value.cbData : lstrlenA(str);
888 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
889 bytesNeeded = 1 + lenBytes + encodedLen;
890 if (!pbEncoded)
891 *pcbEncoded = bytesNeeded;
892 else
894 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
895 pbEncoded, pcbEncoded, bytesNeeded)))
897 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
898 pbEncoded = *(BYTE **)pbEncoded;
899 *pbEncoded++ = tag;
900 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
901 pbEncoded += lenBytes;
902 memcpy(pbEncoded, str, encodedLen);
905 return ret;
908 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
909 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
910 DWORD *pcbEncoded)
912 BOOL ret = TRUE;
913 LPCWSTR str = (LPCWSTR)value->Value.pbData;
914 DWORD bytesNeeded, lenBytes, strLen;
916 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
917 lstrlenW(str);
918 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
919 bytesNeeded = 1 + lenBytes + strLen * 2;
920 if (!pbEncoded)
921 *pcbEncoded = bytesNeeded;
922 else
924 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
925 pbEncoded, pcbEncoded, bytesNeeded)))
927 DWORD i;
929 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
930 pbEncoded = *(BYTE **)pbEncoded;
931 *pbEncoded++ = ASN_BMPSTRING;
932 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
933 pbEncoded += lenBytes;
934 for (i = 0; i < strLen; i++)
936 *pbEncoded++ = (str[i] & 0xff00) >> 8;
937 *pbEncoded++ = str[i] & 0x00ff;
941 return ret;
944 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
945 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
946 DWORD *pcbEncoded)
948 BOOL ret = TRUE;
949 LPCWSTR str = (LPCWSTR)value->Value.pbData;
950 DWORD bytesNeeded, lenBytes, encodedLen, strLen;
952 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
953 lstrlenW(str);
954 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
955 NULL);
956 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
957 bytesNeeded = 1 + lenBytes + encodedLen;
958 if (!pbEncoded)
959 *pcbEncoded = bytesNeeded;
960 else
962 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
963 pbEncoded, pcbEncoded, bytesNeeded)))
965 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
966 pbEncoded = *(BYTE **)pbEncoded;
967 *pbEncoded++ = ASN_UTF8STRING;
968 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
969 pbEncoded += lenBytes;
970 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
971 bytesNeeded - lenBytes - 1, NULL, NULL);
974 return ret;
977 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
978 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
979 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
981 BOOL ret = TRUE;
983 __TRY
985 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
987 switch (value->dwValueType)
989 case CERT_RDN_ANY_TYPE:
990 /* explicitly disallowed */
991 SetLastError(E_INVALIDARG);
992 ret = FALSE;
993 break;
994 case CERT_RDN_ENCODED_BLOB:
995 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
996 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
997 break;
998 case CERT_RDN_OCTET_STRING:
999 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1000 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1001 break;
1002 case CERT_RDN_NUMERIC_STRING:
1003 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1004 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1005 break;
1006 case CERT_RDN_PRINTABLE_STRING:
1007 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1008 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1009 break;
1010 case CERT_RDN_TELETEX_STRING:
1011 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1012 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1013 break;
1014 case CERT_RDN_VIDEOTEX_STRING:
1015 ret = CRYPT_AsnEncodeStringCoerce(value,
1016 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1017 break;
1018 case CERT_RDN_IA5_STRING:
1019 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1020 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1021 break;
1022 case CERT_RDN_GRAPHIC_STRING:
1023 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1024 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1025 break;
1026 case CERT_RDN_VISIBLE_STRING:
1027 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1028 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1029 break;
1030 case CERT_RDN_GENERAL_STRING:
1031 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1032 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1033 break;
1034 case CERT_RDN_UNIVERSAL_STRING:
1035 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1036 SetLastError(CRYPT_E_ASN1_CHOICE);
1037 ret = FALSE;
1038 break;
1039 case CERT_RDN_BMP_STRING:
1040 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1041 pbEncoded, pcbEncoded);
1042 break;
1043 case CERT_RDN_UTF8_STRING:
1044 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1045 pbEncoded, pcbEncoded);
1046 break;
1047 default:
1048 SetLastError(CRYPT_E_ASN1_CHOICE);
1049 ret = FALSE;
1052 __EXCEPT_PAGE_FAULT
1054 SetLastError(STATUS_ACCESS_VIOLATION);
1055 ret = FALSE;
1057 __ENDTRY
1058 return ret;
1061 static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1062 CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1063 BYTE *pbEncoded, DWORD *pcbEncoded)
1065 DWORD bytesNeeded = 0, lenBytes, size;
1066 BOOL ret;
1068 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1069 0, NULL, NULL, &size);
1070 if (ret)
1072 bytesNeeded += size;
1073 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1074 * with dwValueType, so "cast" it to get its encoded size
1076 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1077 (CERT_NAME_VALUE *)&attr->dwValueType, 0, NULL, NULL, &size);
1078 if (ret)
1080 bytesNeeded += size;
1081 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1082 bytesNeeded += 1 + lenBytes;
1083 if (pbEncoded)
1085 if (*pcbEncoded < bytesNeeded)
1087 SetLastError(ERROR_MORE_DATA);
1088 ret = FALSE;
1090 else
1092 *pbEncoded++ = ASN_SEQUENCE;
1093 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1094 &lenBytes);
1095 pbEncoded += lenBytes;
1096 size = bytesNeeded - 1 - lenBytes;
1097 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1098 attr->pszObjId, 0, NULL, pbEncoded, &size);
1099 if (ret)
1101 pbEncoded += size;
1102 size = bytesNeeded - 1 - lenBytes - size;
1103 ret = nameValueEncodeFunc(dwCertEncodingType,
1104 NULL, (CERT_NAME_VALUE *)&attr->dwValueType,
1105 0, NULL, pbEncoded, &size);
1106 if (!ret)
1107 *pcbEncoded = size;
1111 if (ret)
1112 *pcbEncoded = bytesNeeded;
1114 else
1116 /* Have to propagate index of failing character */
1117 *pcbEncoded = size;
1120 return ret;
1123 static int BLOBComp(const void *l, const void *r)
1125 const CRYPT_DER_BLOB *a = (const CRYPT_DER_BLOB *)l, *b = (const CRYPT_DER_BLOB *)r;
1126 int ret;
1128 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1129 ret = a->cbData - b->cbData;
1130 return ret;
1133 typedef struct _CRYPT_SET_OF {
1134 DWORD cValue;
1135 PCRYPT_DER_BLOB rgValue;
1136 } CRYPT_SET_OF;
1138 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1140 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1141 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1142 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1144 const CRYPT_SET_OF *set = (const CRYPT_SET_OF *)pvStructInfo;
1145 DWORD bytesNeeded = 0, lenBytes, i;
1146 BOOL ret;
1148 for (i = 0; i < set->cValue; i++)
1149 bytesNeeded += set->rgValue[i].cbData;
1150 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1151 bytesNeeded += 1 + lenBytes;
1152 if (!pbEncoded)
1154 *pcbEncoded = bytesNeeded;
1155 ret = TRUE;
1157 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1158 pbEncoded, pcbEncoded, bytesNeeded)))
1160 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1161 pbEncoded = *(BYTE **)pbEncoded;
1162 qsort(set->rgValue, set->cValue, sizeof(CRYPT_DER_BLOB), BLOBComp);
1163 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1164 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1165 pbEncoded += lenBytes;
1166 for (i = 0; ret && i < set->cValue; i++)
1168 memcpy(pbEncoded, set->rgValue[i].pbData, set->rgValue[i].cbData);
1169 pbEncoded += set->rgValue[i].cbData;
1172 return ret;
1175 struct DERSetDescriptor
1177 DWORD cItems;
1178 const void *items;
1179 size_t itemSize;
1180 size_t itemOffset;
1181 CryptEncodeObjectExFunc encode;
1184 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,
1185 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1186 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1188 const struct DERSetDescriptor *desc =
1189 (const struct DERSetDescriptor *)pvStructInfo;
1190 CRYPT_SET_OF setOf = { 0, NULL };
1191 BOOL ret = TRUE;
1192 DWORD i;
1194 if (desc->cItems)
1196 setOf.rgValue = CryptMemAlloc(desc->cItems * sizeof(CRYPT_DER_BLOB));
1197 if (!setOf.rgValue)
1198 ret = FALSE;
1199 else
1201 setOf.cValue = desc->cItems;
1202 memset(setOf.rgValue, 0, setOf.cValue * sizeof(CRYPT_DER_BLOB));
1205 for (i = 0; ret && i < setOf.cValue; i++)
1207 ret = desc->encode(dwCertEncodingType, lpszStructType,
1208 (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
1209 0, NULL, NULL, &setOf.rgValue[i].cbData);
1210 if (ret)
1212 setOf.rgValue[i].pbData = CryptMemAlloc(setOf.rgValue[i].cbData);
1213 if (!setOf.rgValue[i].pbData)
1214 ret = FALSE;
1215 else
1216 ret = desc->encode(dwCertEncodingType, lpszStructType,
1217 (const BYTE *)desc->items + i * desc->itemSize +
1218 desc->itemOffset, 0, NULL, setOf.rgValue[i].pbData,
1219 &setOf.rgValue[i].cbData);
1221 /* Some functions propagate their errors through the size */
1222 if (!ret)
1223 *pcbEncoded = setOf.rgValue[i].cbData;
1225 if (ret)
1227 DWORD bytesNeeded = 0, lenBytes;
1228 BOOL ret;
1230 for (i = 0; i < setOf.cValue; i++)
1231 bytesNeeded += setOf.rgValue[i].cbData;
1232 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1233 bytesNeeded += 1 + lenBytes;
1234 if (!pbEncoded)
1235 *pcbEncoded = bytesNeeded;
1236 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1237 pbEncoded, pcbEncoded, bytesNeeded)))
1239 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1240 pbEncoded = *(BYTE **)pbEncoded;
1241 qsort(setOf.rgValue, setOf.cValue, sizeof(CRYPT_DER_BLOB),
1242 BLOBComp);
1243 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1244 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1245 pbEncoded += lenBytes;
1246 for (i = 0; i < setOf.cValue; i++)
1248 memcpy(pbEncoded, setOf.rgValue[i].pbData,
1249 setOf.rgValue[i].cbData);
1250 pbEncoded += setOf.rgValue[i].cbData;
1254 for (i = 0; i < setOf.cValue; i++)
1255 CryptMemFree(setOf.rgValue[i].pbData);
1256 CryptMemFree(setOf.rgValue);
1257 return ret;
1260 static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
1261 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1262 DWORD *pcbEncoded)
1264 BOOL ret;
1265 CRYPT_SET_OF setOf = { 0, NULL };
1267 __TRY
1269 DWORD i;
1271 ret = TRUE;
1272 if (rdn->cRDNAttr)
1274 setOf.cValue = rdn->cRDNAttr;
1275 setOf.rgValue = CryptMemAlloc(rdn->cRDNAttr *
1276 sizeof(CRYPT_DER_BLOB));
1277 if (!setOf.rgValue)
1278 ret = FALSE;
1279 else
1280 memset(setOf.rgValue, 0, setOf.cValue * sizeof(CRYPT_DER_BLOB));
1282 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1284 setOf.rgValue[i].cbData = 0;
1285 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1286 nameValueEncodeFunc, NULL, &setOf.rgValue[i].cbData);
1287 if (ret)
1289 setOf.rgValue[i].pbData =
1290 CryptMemAlloc(setOf.rgValue[i].cbData);
1291 if (!setOf.rgValue[i].pbData)
1292 ret = FALSE;
1293 else
1294 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1295 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1296 setOf.rgValue[i].pbData, &setOf.rgValue[i].cbData);
1298 if (!ret)
1300 /* Have to propagate index of failing character */
1301 *pcbEncoded = setOf.rgValue[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.cValue; i++)
1308 CryptMemFree(setOf.rgValue[i].pbData);
1310 __EXCEPT_PAGE_FAULT
1312 SetLastError(STATUS_ACCESS_VIOLATION);
1313 ret = FALSE;
1315 __ENDTRY
1316 CryptMemFree(setOf.rgValue);
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_AsnEncodePKCSAttribute(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_ATTRIBUTE *attr = (const CRYPT_ATTRIBUTE *)pvStructInfo;
1417 if (!attr->pszObjId)
1418 SetLastError(E_INVALIDARG);
1419 else
1421 struct AsnEncodeSequenceItem items[2] = {
1422 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1423 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1426 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1427 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1428 pcbEncoded);
1431 __EXCEPT_PAGE_FAULT
1433 SetLastError(STATUS_ACCESS_VIOLATION);
1435 __ENDTRY
1436 return ret;
1439 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1440 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1441 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1443 BOOL ret = FALSE;
1445 __TRY
1447 const CRYPT_ATTRIBUTES *attributes =
1448 (const CRYPT_ATTRIBUTES *)pvStructInfo;
1449 struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
1450 sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
1452 ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
1453 &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1455 __EXCEPT_PAGE_FAULT
1457 SetLastError(STATUS_ACCESS_VIOLATION);
1459 __ENDTRY
1460 return ret;
1463 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1464 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
1465 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1466 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1467 DWORD *pcbEncoded)
1469 const CRYPT_CONTENT_INFO *info = (const CRYPT_CONTENT_INFO *)pvStructInfo;
1470 struct AsnEncodeSequenceItem items[2] = {
1471 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1472 { NULL, NULL, 0 },
1474 struct AsnConstructedItem constructed = { 0 };
1475 DWORD cItem = 1;
1477 if (info->Content.cbData)
1479 constructed.tag = 0;
1480 constructed.pvStructInfo = &info->Content;
1481 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1482 items[cItem].pvStructInfo = &constructed;
1483 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1484 cItem++;
1486 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1487 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1490 BOOL CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA *digestedData,
1491 void *pvData, DWORD *pcbData)
1493 struct AsnEncodeSequenceItem items[] = {
1494 { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1495 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
1496 0 },
1497 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1498 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1501 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1502 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
1505 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1506 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1507 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1509 BOOL ret = FALSE;
1511 __TRY
1513 const CRYPT_CONTENT_INFO *info =
1514 (const CRYPT_CONTENT_INFO *)pvStructInfo;
1516 if (!info->pszObjId)
1517 SetLastError(E_INVALIDARG);
1518 else
1519 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
1520 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1521 pcbEncoded);
1523 __EXCEPT_PAGE_FAULT
1525 SetLastError(STATUS_ACCESS_VIOLATION);
1527 __ENDTRY
1528 return ret;
1531 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1532 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1533 DWORD *pcbEncoded)
1535 BOOL ret = TRUE;
1536 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1537 DWORD bytesNeeded, lenBytes, encodedLen;
1539 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1540 lstrlenW(str);
1541 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1542 bytesNeeded = 1 + lenBytes + encodedLen;
1543 if (!pbEncoded)
1544 *pcbEncoded = bytesNeeded;
1545 else
1547 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1548 pbEncoded, pcbEncoded, bytesNeeded)))
1550 DWORD i;
1552 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1553 pbEncoded = *(BYTE **)pbEncoded;
1554 *pbEncoded++ = tag;
1555 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1556 pbEncoded += lenBytes;
1557 for (i = 0; i < encodedLen; i++)
1558 *pbEncoded++ = (BYTE)str[i];
1561 return ret;
1564 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
1565 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1566 DWORD *pcbEncoded)
1568 BOOL ret = TRUE;
1569 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1570 DWORD bytesNeeded, lenBytes, encodedLen;
1572 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1573 lstrlenW(str);
1574 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1575 bytesNeeded = 1 + lenBytes + encodedLen;
1576 if (!pbEncoded)
1577 *pcbEncoded = bytesNeeded;
1578 else
1580 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1581 pbEncoded, pcbEncoded, bytesNeeded)))
1583 DWORD i;
1585 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1586 pbEncoded = *(BYTE **)pbEncoded;
1587 *pbEncoded++ = ASN_NUMERICSTRING;
1588 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1589 pbEncoded += lenBytes;
1590 for (i = 0; ret && i < encodedLen; i++)
1592 if (isdigitW(str[i]))
1593 *pbEncoded++ = (BYTE)str[i];
1594 else
1596 *pcbEncoded = i;
1597 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
1598 ret = FALSE;
1603 return ret;
1606 static inline int isprintableW(WCHAR wc)
1608 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
1609 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
1610 wc == '/' || wc == ':' || wc == '=' || wc == '?';
1613 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
1614 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1615 DWORD *pcbEncoded)
1617 BOOL ret = TRUE;
1618 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1619 DWORD bytesNeeded, lenBytes, encodedLen;
1621 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1622 lstrlenW(str);
1623 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1624 bytesNeeded = 1 + lenBytes + encodedLen;
1625 if (!pbEncoded)
1626 *pcbEncoded = bytesNeeded;
1627 else
1629 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1630 pbEncoded, pcbEncoded, bytesNeeded)))
1632 DWORD i;
1634 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1635 pbEncoded = *(BYTE **)pbEncoded;
1636 *pbEncoded++ = ASN_PRINTABLESTRING;
1637 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1638 pbEncoded += lenBytes;
1639 for (i = 0; ret && i < encodedLen; i++)
1641 if (isprintableW(str[i]))
1642 *pbEncoded++ = (BYTE)str[i];
1643 else
1645 *pcbEncoded = i;
1646 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
1647 ret = FALSE;
1652 return ret;
1655 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
1656 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1657 DWORD *pcbEncoded)
1659 BOOL ret = TRUE;
1660 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1661 DWORD bytesNeeded, lenBytes, encodedLen;
1663 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1664 lstrlenW(str);
1665 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1666 bytesNeeded = 1 + lenBytes + encodedLen;
1667 if (!pbEncoded)
1668 *pcbEncoded = bytesNeeded;
1669 else
1671 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1672 pbEncoded, pcbEncoded, bytesNeeded)))
1674 DWORD i;
1676 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1677 pbEncoded = *(BYTE **)pbEncoded;
1678 *pbEncoded++ = ASN_IA5STRING;
1679 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1680 pbEncoded += lenBytes;
1681 for (i = 0; ret && i < encodedLen; i++)
1683 if (str[i] <= 0x7f)
1684 *pbEncoded++ = (BYTE)str[i];
1685 else
1687 *pcbEncoded = i;
1688 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1689 ret = FALSE;
1694 return ret;
1697 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
1698 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1699 DWORD *pcbEncoded)
1701 BOOL ret = TRUE;
1702 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1703 DWORD bytesNeeded, lenBytes, strLen;
1705 /* FIXME: doesn't handle composite characters */
1706 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1707 lstrlenW(str);
1708 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
1709 bytesNeeded = 1 + lenBytes + strLen * 4;
1710 if (!pbEncoded)
1711 *pcbEncoded = bytesNeeded;
1712 else
1714 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1715 pbEncoded, pcbEncoded, bytesNeeded)))
1717 DWORD i;
1719 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1720 pbEncoded = *(BYTE **)pbEncoded;
1721 *pbEncoded++ = ASN_UNIVERSALSTRING;
1722 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
1723 pbEncoded += lenBytes;
1724 for (i = 0; i < strLen; i++)
1726 *pbEncoded++ = 0;
1727 *pbEncoded++ = 0;
1728 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
1729 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
1733 return ret;
1736 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1737 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1738 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1740 BOOL ret = FALSE;
1742 __TRY
1744 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1746 switch (value->dwValueType)
1748 case CERT_RDN_ANY_TYPE:
1749 case CERT_RDN_ENCODED_BLOB:
1750 case CERT_RDN_OCTET_STRING:
1751 SetLastError(CRYPT_E_NOT_CHAR_STRING);
1752 break;
1753 case CERT_RDN_NUMERIC_STRING:
1754 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
1755 pbEncoded, pcbEncoded);
1756 break;
1757 case CERT_RDN_PRINTABLE_STRING:
1758 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
1759 pbEncoded, pcbEncoded);
1760 break;
1761 case CERT_RDN_TELETEX_STRING:
1762 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
1763 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1764 break;
1765 case CERT_RDN_VIDEOTEX_STRING:
1766 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
1767 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1768 break;
1769 case CERT_RDN_IA5_STRING:
1770 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
1771 pbEncoded, pcbEncoded);
1772 break;
1773 case CERT_RDN_GRAPHIC_STRING:
1774 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
1775 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1776 break;
1777 case CERT_RDN_VISIBLE_STRING:
1778 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
1779 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1780 break;
1781 case CERT_RDN_GENERAL_STRING:
1782 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
1783 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1784 break;
1785 case CERT_RDN_UNIVERSAL_STRING:
1786 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
1787 pbEncoded, pcbEncoded);
1788 break;
1789 case CERT_RDN_BMP_STRING:
1790 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1791 pbEncoded, pcbEncoded);
1792 break;
1793 case CERT_RDN_UTF8_STRING:
1794 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1795 pbEncoded, pcbEncoded);
1796 break;
1797 default:
1798 SetLastError(CRYPT_E_ASN1_CHOICE);
1801 __EXCEPT_PAGE_FAULT
1803 SetLastError(STATUS_ACCESS_VIOLATION);
1805 __ENDTRY
1806 return ret;
1809 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
1810 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1811 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1813 BOOL ret;
1815 __TRY
1817 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1818 DWORD bytesNeeded = 0, lenBytes, size, i;
1820 TRACE("encoding name with %d RDNs\n", info->cRDN);
1821 ret = TRUE;
1822 for (i = 0; ret && i < info->cRDN; i++)
1824 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1825 CRYPT_AsnEncodeNameValue, NULL, &size);
1826 if (ret)
1827 bytesNeeded += size;
1829 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1830 bytesNeeded += 1 + lenBytes;
1831 if (ret)
1833 if (!pbEncoded)
1834 *pcbEncoded = bytesNeeded;
1835 else
1837 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1838 pbEncoded, pcbEncoded, bytesNeeded)))
1840 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1841 pbEncoded = *(BYTE **)pbEncoded;
1842 *pbEncoded++ = ASN_SEQUENCEOF;
1843 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1844 &lenBytes);
1845 pbEncoded += lenBytes;
1846 for (i = 0; ret && i < info->cRDN; i++)
1848 size = bytesNeeded;
1849 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1850 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, pbEncoded,
1851 &size);
1852 if (ret)
1854 pbEncoded += size;
1855 bytesNeeded -= size;
1862 __EXCEPT_PAGE_FAULT
1864 SetLastError(STATUS_ACCESS_VIOLATION);
1865 ret = FALSE;
1867 __ENDTRY
1868 return ret;
1871 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1872 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1873 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1875 BOOL val = *(const BOOL *)pvStructInfo, ret;
1877 TRACE("%d\n", val);
1879 if (!pbEncoded)
1881 *pcbEncoded = 3;
1882 ret = TRUE;
1884 else if (*pcbEncoded < 3)
1886 *pcbEncoded = 3;
1887 SetLastError(ERROR_MORE_DATA);
1888 ret = FALSE;
1890 else
1892 *pcbEncoded = 3;
1893 *pbEncoded++ = ASN_BOOL;
1894 *pbEncoded++ = 1;
1895 *pbEncoded++ = val ? 0xff : 0;
1896 ret = TRUE;
1898 TRACE("returning %d (%08x)\n", ret, GetLastError());
1899 return ret;
1902 static BOOL CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY *entry,
1903 BYTE *pbEncoded, DWORD *pcbEncoded)
1905 BOOL ret;
1906 DWORD dataLen;
1907 BYTE tag;
1909 ret = TRUE;
1910 switch (entry->dwAltNameChoice)
1912 case CERT_ALT_NAME_RFC822_NAME:
1913 case CERT_ALT_NAME_DNS_NAME:
1914 case CERT_ALT_NAME_URL:
1915 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1916 if (entry->u.pwszURL)
1918 DWORD i;
1920 /* Not + 1: don't encode the NULL-terminator */
1921 dataLen = lstrlenW(entry->u.pwszURL);
1922 for (i = 0; ret && i < dataLen; i++)
1924 if (entry->u.pwszURL[i] > 0x7f)
1926 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1927 ret = FALSE;
1928 *pcbEncoded = i;
1932 else
1933 dataLen = 0;
1934 break;
1935 case CERT_ALT_NAME_DIRECTORY_NAME:
1936 tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1);
1937 dataLen = entry->u.DirectoryName.cbData;
1938 break;
1939 case CERT_ALT_NAME_IP_ADDRESS:
1940 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1941 dataLen = entry->u.IPAddress.cbData;
1942 break;
1943 case CERT_ALT_NAME_REGISTERED_ID:
1945 struct AsnEncodeTagSwappedItem swapped =
1946 { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID,
1947 CRYPT_AsnEncodeOid };
1949 return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded,
1950 pcbEncoded);
1952 case CERT_ALT_NAME_OTHER_NAME:
1953 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
1954 return FALSE;
1955 default:
1956 SetLastError(E_INVALIDARG);
1957 return FALSE;
1959 if (ret)
1961 DWORD bytesNeeded, lenBytes;
1963 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1964 bytesNeeded = 1 + dataLen + lenBytes;
1965 if (!pbEncoded)
1966 *pcbEncoded = bytesNeeded;
1967 else if (*pcbEncoded < bytesNeeded)
1969 SetLastError(ERROR_MORE_DATA);
1970 *pcbEncoded = bytesNeeded;
1971 ret = FALSE;
1973 else
1975 *pbEncoded++ = tag;
1976 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1977 pbEncoded += lenBytes;
1978 switch (entry->dwAltNameChoice)
1980 case CERT_ALT_NAME_RFC822_NAME:
1981 case CERT_ALT_NAME_DNS_NAME:
1982 case CERT_ALT_NAME_URL:
1984 DWORD i;
1986 for (i = 0; i < dataLen; i++)
1987 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
1988 break;
1990 case CERT_ALT_NAME_DIRECTORY_NAME:
1991 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen);
1992 break;
1993 case CERT_ALT_NAME_IP_ADDRESS:
1994 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
1995 break;
1997 if (ret)
1998 *pcbEncoded = bytesNeeded;
2001 TRACE("returning %d (%08x)\n", ret, GetLastError());
2002 return ret;
2005 static BOOL WINAPI CRYPT_AsnEncodeIntegerSwapBytes(DWORD dwCertEncodingType,
2006 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2007 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2009 BOOL ret;
2011 __TRY
2013 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2014 CRYPT_DATA_BLOB newBlob = { blob->cbData, NULL };
2016 ret = TRUE;
2017 if (newBlob.cbData)
2019 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2020 if (newBlob.pbData)
2022 DWORD i;
2024 for (i = 0; i < newBlob.cbData; i++)
2025 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2027 else
2028 ret = FALSE;
2030 if (ret)
2031 ret = CRYPT_AsnEncodeInteger(dwCertEncodingType, lpszStructType,
2032 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2033 CryptMemFree(newBlob.pbData);
2035 __EXCEPT_PAGE_FAULT
2037 SetLastError(STATUS_ACCESS_VIOLATION);
2038 ret = FALSE;
2040 __ENDTRY
2041 return ret;
2044 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
2045 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2046 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2048 BOOL ret;
2050 __TRY
2052 const CERT_AUTHORITY_KEY_ID_INFO *info =
2053 (const CERT_AUTHORITY_KEY_ID_INFO *)pvStructInfo;
2054 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2055 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2056 struct AsnConstructedItem constructed = { 0 };
2057 DWORD cItem = 0, cSwapped = 0;
2059 if (info->KeyId.cbData)
2061 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2062 swapped[cSwapped].pvStructInfo = &info->KeyId;
2063 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2064 items[cItem].pvStructInfo = &swapped[cSwapped];
2065 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2066 cSwapped++;
2067 cItem++;
2069 if (info->CertIssuer.cbData)
2071 constructed.tag = 1;
2072 constructed.pvStructInfo = &info->CertIssuer;
2073 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2074 items[cItem].pvStructInfo = &constructed;
2075 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2076 cItem++;
2078 if (info->CertSerialNumber.cbData)
2080 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2081 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2082 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2083 items[cItem].pvStructInfo = &swapped[cSwapped];
2084 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2085 cSwapped++;
2086 cItem++;
2088 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2089 pEncodePara, pbEncoded, pcbEncoded);
2091 __EXCEPT_PAGE_FAULT
2093 SetLastError(STATUS_ACCESS_VIOLATION);
2094 ret = FALSE;
2096 __ENDTRY
2097 return ret;
2100 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2101 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2102 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2104 BOOL ret;
2106 __TRY
2108 const CERT_ALT_NAME_INFO *info =
2109 (const CERT_ALT_NAME_INFO *)pvStructInfo;
2110 DWORD bytesNeeded, dataLen, lenBytes, i;
2112 ret = TRUE;
2113 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2114 * can't encode an erroneous entry index if it's bigger than this.
2116 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2118 DWORD len;
2120 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i], NULL,
2121 &len);
2122 if (ret)
2123 dataLen += len;
2124 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2126 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2127 * the bad character, now set the index of the bad
2128 * entry
2130 *pcbEncoded = (BYTE)i <<
2131 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2134 if (ret)
2136 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2137 bytesNeeded = 1 + lenBytes + dataLen;
2138 if (!pbEncoded)
2140 *pcbEncoded = bytesNeeded;
2141 ret = TRUE;
2143 else
2145 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2146 pbEncoded, pcbEncoded, bytesNeeded)))
2148 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2149 pbEncoded = *(BYTE **)pbEncoded;
2150 *pbEncoded++ = ASN_SEQUENCEOF;
2151 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2152 pbEncoded += lenBytes;
2153 for (i = 0; ret && i < info->cAltEntry; i++)
2155 DWORD len = dataLen;
2157 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i],
2158 pbEncoded, &len);
2159 if (ret)
2161 pbEncoded += len;
2162 dataLen -= len;
2169 __EXCEPT_PAGE_FAULT
2171 SetLastError(STATUS_ACCESS_VIOLATION);
2172 ret = FALSE;
2174 __ENDTRY
2175 return ret;
2178 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2179 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2180 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2182 BOOL ret;
2184 __TRY
2186 const CERT_AUTHORITY_KEY_ID2_INFO *info =
2187 (const CERT_AUTHORITY_KEY_ID2_INFO *)pvStructInfo;
2188 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2189 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2190 DWORD cItem = 0, cSwapped = 0;
2192 if (info->KeyId.cbData)
2194 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2195 swapped[cSwapped].pvStructInfo = &info->KeyId;
2196 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2197 items[cItem].pvStructInfo = &swapped[cSwapped];
2198 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2199 cSwapped++;
2200 cItem++;
2202 if (info->AuthorityCertIssuer.cAltEntry)
2204 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2205 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2206 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2207 items[cItem].pvStructInfo = &swapped[cSwapped];
2208 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2209 cSwapped++;
2210 cItem++;
2212 if (info->AuthorityCertSerialNumber.cbData)
2214 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2215 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2216 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2217 items[cItem].pvStructInfo = &swapped[cSwapped];
2218 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2219 cSwapped++;
2220 cItem++;
2222 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2223 pEncodePara, pbEncoded, pcbEncoded);
2225 __EXCEPT_PAGE_FAULT
2227 SetLastError(STATUS_ACCESS_VIOLATION);
2228 ret = FALSE;
2230 __ENDTRY
2231 return ret;
2234 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2235 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2236 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2238 BOOL ret;
2240 __TRY
2242 const CERT_BASIC_CONSTRAINTS_INFO *info =
2243 (const CERT_BASIC_CONSTRAINTS_INFO *)pvStructInfo;
2244 struct AsnEncodeSequenceItem items[3] = {
2245 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2246 { 0 }
2248 DWORD cItem = 1;
2250 if (info->fPathLenConstraint)
2252 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2253 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2254 cItem++;
2256 if (info->cSubtreesConstraint)
2258 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2259 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2260 cItem++;
2262 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2263 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2265 __EXCEPT_PAGE_FAULT
2267 SetLastError(STATUS_ACCESS_VIOLATION);
2268 ret = FALSE;
2270 __ENDTRY
2271 return ret;
2274 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2275 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2276 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2278 BOOL ret;
2280 __TRY
2282 const CERT_BASIC_CONSTRAINTS2_INFO *info =
2283 (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
2284 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2285 DWORD cItem = 0;
2287 if (info->fCA)
2289 items[cItem].pvStructInfo = &info->fCA;
2290 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2291 cItem++;
2293 if (info->fPathLenConstraint)
2295 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2296 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2297 cItem++;
2299 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2300 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2302 __EXCEPT_PAGE_FAULT
2304 SetLastError(STATUS_ACCESS_VIOLATION);
2305 ret = FALSE;
2307 __ENDTRY
2308 return ret;
2311 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
2312 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2313 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2315 BOOL ret;
2317 __TRY
2319 const BLOBHEADER *hdr =
2320 (const BLOBHEADER *)pvStructInfo;
2322 if (hdr->bType != PUBLICKEYBLOB)
2324 SetLastError(E_INVALIDARG);
2325 ret = FALSE;
2327 else
2329 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
2330 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
2331 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
2332 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
2333 struct AsnEncodeSequenceItem items[] = {
2334 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
2335 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
2338 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2339 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
2340 pcbEncoded);
2343 __EXCEPT_PAGE_FAULT
2345 SetLastError(STATUS_ACCESS_VIOLATION);
2346 ret = FALSE;
2348 __ENDTRY
2349 return ret;
2352 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
2353 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2354 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2356 BOOL ret;
2358 __TRY
2360 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2361 DWORD bytesNeeded, lenBytes;
2363 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
2364 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
2366 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
2367 bytesNeeded = 1 + lenBytes + blob->cbData;
2368 if (!pbEncoded)
2370 *pcbEncoded = bytesNeeded;
2371 ret = TRUE;
2373 else
2375 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2376 pcbEncoded, bytesNeeded)))
2378 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2379 pbEncoded = *(BYTE **)pbEncoded;
2380 *pbEncoded++ = ASN_OCTETSTRING;
2381 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
2382 pbEncoded += lenBytes;
2383 if (blob->cbData)
2384 memcpy(pbEncoded, blob->pbData, blob->cbData);
2388 __EXCEPT_PAGE_FAULT
2390 SetLastError(STATUS_ACCESS_VIOLATION);
2391 ret = FALSE;
2393 __ENDTRY
2394 TRACE("returning %d (%08x)\n", ret, GetLastError());
2395 return ret;
2398 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
2399 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2400 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2402 BOOL ret;
2404 __TRY
2406 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2407 DWORD bytesNeeded, lenBytes, dataBytes;
2408 BYTE unusedBits;
2410 /* yep, MS allows cUnusedBits to be >= 8 */
2411 if (!blob->cUnusedBits)
2413 dataBytes = blob->cbData;
2414 unusedBits = 0;
2416 else if (blob->cbData * 8 > blob->cUnusedBits)
2418 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
2419 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
2420 blob->cUnusedBits;
2422 else
2424 dataBytes = 0;
2425 unusedBits = 0;
2427 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
2428 bytesNeeded = 1 + lenBytes + dataBytes + 1;
2429 if (!pbEncoded)
2431 *pcbEncoded = bytesNeeded;
2432 ret = TRUE;
2434 else
2436 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2437 pcbEncoded, bytesNeeded)))
2439 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2440 pbEncoded = *(BYTE **)pbEncoded;
2441 *pbEncoded++ = ASN_BITSTRING;
2442 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
2443 pbEncoded += lenBytes;
2444 *pbEncoded++ = unusedBits;
2445 if (dataBytes)
2447 BYTE mask = 0xff << unusedBits;
2449 if (dataBytes > 1)
2451 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
2452 pbEncoded += dataBytes - 1;
2454 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
2459 __EXCEPT_PAGE_FAULT
2461 SetLastError(STATUS_ACCESS_VIOLATION);
2462 ret = FALSE;
2464 __ENDTRY
2465 return ret;
2468 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(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_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2477 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
2479 ret = TRUE;
2480 if (newBlob.cbData)
2482 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2483 if (newBlob.pbData)
2485 DWORD i;
2487 for (i = 0; i < newBlob.cbData; i++)
2488 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2490 else
2491 ret = FALSE;
2493 if (ret)
2494 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
2495 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2496 CryptMemFree(newBlob.pbData);
2498 __EXCEPT_PAGE_FAULT
2500 SetLastError(STATUS_ACCESS_VIOLATION);
2501 ret = FALSE;
2503 __ENDTRY
2504 return ret;
2507 BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
2508 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2509 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2511 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
2513 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
2514 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2517 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
2518 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2519 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2521 BOOL ret;
2523 __TRY
2525 DWORD significantBytes, lenBytes;
2526 BYTE padByte = 0, bytesNeeded;
2527 BOOL pad = FALSE;
2528 const CRYPT_INTEGER_BLOB *blob =
2529 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2531 significantBytes = blob->cbData;
2532 if (significantBytes)
2534 if (blob->pbData[significantBytes - 1] & 0x80)
2536 /* negative, lop off leading (little-endian) 0xffs */
2537 for (; significantBytes > 0 &&
2538 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
2540 if (blob->pbData[significantBytes - 1] < 0x80)
2542 padByte = 0xff;
2543 pad = TRUE;
2546 else
2548 /* positive, lop off leading (little-endian) zeroes */
2549 for (; significantBytes > 0 &&
2550 !blob->pbData[significantBytes - 1]; significantBytes--)
2552 if (significantBytes == 0)
2553 significantBytes = 1;
2554 if (blob->pbData[significantBytes - 1] > 0x7f)
2556 padByte = 0;
2557 pad = TRUE;
2561 if (pad)
2562 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2563 else
2564 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2565 bytesNeeded = 1 + lenBytes + significantBytes;
2566 if (pad)
2567 bytesNeeded++;
2568 if (!pbEncoded)
2570 *pcbEncoded = bytesNeeded;
2571 ret = TRUE;
2573 else
2575 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2576 pcbEncoded, bytesNeeded)))
2578 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2579 pbEncoded = *(BYTE **)pbEncoded;
2580 *pbEncoded++ = ASN_INTEGER;
2581 if (pad)
2583 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2584 pbEncoded += lenBytes;
2585 *pbEncoded++ = padByte;
2587 else
2589 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2590 pbEncoded += lenBytes;
2592 for (; significantBytes > 0; significantBytes--)
2593 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2597 __EXCEPT_PAGE_FAULT
2599 SetLastError(STATUS_ACCESS_VIOLATION);
2600 ret = FALSE;
2602 __ENDTRY
2603 return ret;
2606 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
2607 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2608 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2610 BOOL ret;
2612 __TRY
2614 DWORD significantBytes, lenBytes;
2615 BYTE bytesNeeded;
2616 BOOL pad = FALSE;
2617 const CRYPT_INTEGER_BLOB *blob =
2618 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2620 significantBytes = blob->cbData;
2621 if (significantBytes)
2623 /* positive, lop off leading (little-endian) zeroes */
2624 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
2625 significantBytes--)
2627 if (significantBytes == 0)
2628 significantBytes = 1;
2629 if (blob->pbData[significantBytes - 1] > 0x7f)
2630 pad = TRUE;
2632 if (pad)
2633 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2634 else
2635 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2636 bytesNeeded = 1 + lenBytes + significantBytes;
2637 if (pad)
2638 bytesNeeded++;
2639 if (!pbEncoded)
2641 *pcbEncoded = bytesNeeded;
2642 ret = TRUE;
2644 else
2646 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2647 pcbEncoded, bytesNeeded)))
2649 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2650 pbEncoded = *(BYTE **)pbEncoded;
2651 *pbEncoded++ = ASN_INTEGER;
2652 if (pad)
2654 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2655 pbEncoded += lenBytes;
2656 *pbEncoded++ = 0;
2658 else
2660 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2661 pbEncoded += lenBytes;
2663 for (; significantBytes > 0; significantBytes--)
2664 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2668 __EXCEPT_PAGE_FAULT
2670 SetLastError(STATUS_ACCESS_VIOLATION);
2671 ret = FALSE;
2673 __ENDTRY
2674 return ret;
2677 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
2678 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2679 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2681 CRYPT_INTEGER_BLOB blob;
2682 BOOL ret;
2684 /* Encode as an unsigned integer, then change the tag to enumerated */
2685 blob.cbData = sizeof(DWORD);
2686 blob.pbData = (BYTE *)pvStructInfo;
2687 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
2688 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2689 if (ret && pbEncoded)
2691 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2692 pbEncoded = *(BYTE **)pbEncoded;
2693 pbEncoded[0] = ASN_ENUMERATED;
2695 return ret;
2698 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
2699 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2700 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2702 BOOL ret;
2704 __TRY
2706 SYSTEMTIME sysTime;
2707 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2708 * temporary buffer because the output buffer is not NULL-terminated.
2710 char buf[16];
2711 static const DWORD bytesNeeded = sizeof(buf) - 1;
2713 if (!pbEncoded)
2715 *pcbEncoded = bytesNeeded;
2716 ret = TRUE;
2718 else
2720 /* Sanity check the year, this is a two-digit year format */
2721 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2722 &sysTime);
2723 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
2725 SetLastError(CRYPT_E_BAD_ENCODE);
2726 ret = FALSE;
2728 if (ret)
2730 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2731 pbEncoded, pcbEncoded, bytesNeeded)))
2733 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2734 pbEncoded = *(BYTE **)pbEncoded;
2735 buf[0] = ASN_UTCTIME;
2736 buf[1] = bytesNeeded - 2;
2737 snprintf(buf + 2, sizeof(buf) - 2,
2738 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
2739 sysTime.wYear - 2000 : sysTime.wYear - 1900,
2740 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2741 sysTime.wMinute, sysTime.wSecond);
2742 memcpy(pbEncoded, buf, bytesNeeded);
2747 __EXCEPT_PAGE_FAULT
2749 SetLastError(STATUS_ACCESS_VIOLATION);
2750 ret = FALSE;
2752 __ENDTRY
2753 return ret;
2756 static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
2757 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2758 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2760 BOOL ret;
2762 __TRY
2764 SYSTEMTIME sysTime;
2765 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2766 * temporary buffer because the output buffer is not NULL-terminated.
2768 char buf[18];
2769 static const DWORD bytesNeeded = sizeof(buf) - 1;
2771 if (!pbEncoded)
2773 *pcbEncoded = bytesNeeded;
2774 ret = TRUE;
2776 else
2778 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2779 &sysTime);
2780 if (ret)
2781 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2782 pcbEncoded, bytesNeeded);
2783 if (ret)
2785 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2786 pbEncoded = *(BYTE **)pbEncoded;
2787 buf[0] = ASN_GENERALTIME;
2788 buf[1] = bytesNeeded - 2;
2789 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
2790 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2791 sysTime.wMinute, sysTime.wSecond);
2792 memcpy(pbEncoded, buf, bytesNeeded);
2796 __EXCEPT_PAGE_FAULT
2798 SetLastError(STATUS_ACCESS_VIOLATION);
2799 ret = FALSE;
2801 __ENDTRY
2802 return ret;
2805 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
2806 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2807 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2809 BOOL ret;
2811 __TRY
2813 SYSTEMTIME sysTime;
2815 /* Check the year, if it's in the UTCTime range call that encode func */
2816 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
2817 return FALSE;
2818 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
2819 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
2820 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2821 else
2822 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
2823 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
2824 pcbEncoded);
2826 __EXCEPT_PAGE_FAULT
2828 SetLastError(STATUS_ACCESS_VIOLATION);
2829 ret = FALSE;
2831 __ENDTRY
2832 return ret;
2835 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
2836 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2837 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2839 BOOL ret;
2841 __TRY
2843 DWORD bytesNeeded, dataLen, lenBytes, i;
2844 const CRYPT_SEQUENCE_OF_ANY *seq =
2845 (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2847 for (i = 0, dataLen = 0; i < seq->cValue; i++)
2848 dataLen += seq->rgValue[i].cbData;
2849 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2850 bytesNeeded = 1 + lenBytes + dataLen;
2851 if (!pbEncoded)
2853 *pcbEncoded = bytesNeeded;
2854 ret = TRUE;
2856 else
2858 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2859 pcbEncoded, bytesNeeded)))
2861 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2862 pbEncoded = *(BYTE **)pbEncoded;
2863 *pbEncoded++ = ASN_SEQUENCEOF;
2864 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2865 pbEncoded += lenBytes;
2866 for (i = 0; i < seq->cValue; i++)
2868 memcpy(pbEncoded, seq->rgValue[i].pbData,
2869 seq->rgValue[i].cbData);
2870 pbEncoded += seq->rgValue[i].cbData;
2875 __EXCEPT_PAGE_FAULT
2877 SetLastError(STATUS_ACCESS_VIOLATION);
2878 ret = FALSE;
2880 __ENDTRY
2881 return ret;
2884 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
2885 BYTE *pbEncoded, DWORD *pcbEncoded)
2887 BOOL ret = TRUE;
2888 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2889 struct AsnConstructedItem constructed = { 0 };
2890 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2891 DWORD cItem = 0, cSwapped = 0;
2893 switch (distPoint->DistPointName.dwDistPointNameChoice)
2895 case CRL_DIST_POINT_NO_NAME:
2896 /* do nothing */
2897 break;
2898 case CRL_DIST_POINT_FULL_NAME:
2899 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
2900 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
2901 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2902 constructed.tag = 0;
2903 constructed.pvStructInfo = &swapped[cSwapped];
2904 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
2905 items[cItem].pvStructInfo = &constructed;
2906 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2907 cSwapped++;
2908 cItem++;
2909 break;
2910 case CRL_DIST_POINT_ISSUER_RDN_NAME:
2911 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2912 ret = FALSE;
2913 break;
2914 default:
2915 ret = FALSE;
2917 if (ret && distPoint->ReasonFlags.cbData)
2919 swapped[cSwapped].tag = ASN_CONTEXT | 1;
2920 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
2921 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
2922 items[cItem].pvStructInfo = &swapped[cSwapped];
2923 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2924 cSwapped++;
2925 cItem++;
2927 if (ret && distPoint->CRLIssuer.cAltEntry)
2929 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
2930 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
2931 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2932 items[cItem].pvStructInfo = &swapped[cSwapped];
2933 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2934 cSwapped++;
2935 cItem++;
2937 if (ret)
2938 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
2939 pbEncoded, pcbEncoded);
2940 return ret;
2943 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
2944 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2945 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2947 BOOL ret;
2949 __TRY
2951 const CRL_DIST_POINTS_INFO *info =
2952 (const CRL_DIST_POINTS_INFO *)pvStructInfo;
2954 if (!info->cDistPoint)
2956 SetLastError(E_INVALIDARG);
2957 ret = FALSE;
2959 else
2961 DWORD bytesNeeded, dataLen, lenBytes, i;
2963 ret = TRUE;
2964 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
2966 DWORD len;
2968 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
2969 &len);
2970 if (ret)
2971 dataLen += len;
2972 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2974 /* Have to propagate index of failing character */
2975 *pcbEncoded = len;
2978 if (ret)
2980 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2981 bytesNeeded = 1 + lenBytes + dataLen;
2982 if (!pbEncoded)
2984 *pcbEncoded = bytesNeeded;
2985 ret = TRUE;
2987 else
2989 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2990 pbEncoded, pcbEncoded, bytesNeeded)))
2992 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2993 pbEncoded = *(BYTE **)pbEncoded;
2994 *pbEncoded++ = ASN_SEQUENCEOF;
2995 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2996 pbEncoded += lenBytes;
2997 for (i = 0; ret && i < info->cDistPoint; i++)
2999 DWORD len = dataLen;
3001 ret = CRYPT_AsnEncodeDistPoint(
3002 &info->rgDistPoint[i], pbEncoded, &len);
3003 if (ret)
3005 pbEncoded += len;
3006 dataLen -= len;
3014 __EXCEPT_PAGE_FAULT
3016 SetLastError(STATUS_ACCESS_VIOLATION);
3017 ret = FALSE;
3019 __ENDTRY
3020 return ret;
3023 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3024 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3025 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3027 BOOL ret;
3029 __TRY
3031 const CERT_ENHKEY_USAGE *usage =
3032 (const CERT_ENHKEY_USAGE *)pvStructInfo;
3033 DWORD bytesNeeded = 0, lenBytes, size, i;
3035 ret = TRUE;
3036 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3038 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3039 usage->rgpszUsageIdentifier[i],
3040 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
3041 if (ret)
3042 bytesNeeded += size;
3044 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3045 bytesNeeded += 1 + lenBytes;
3046 if (ret)
3048 if (!pbEncoded)
3049 *pcbEncoded = bytesNeeded;
3050 else
3052 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3053 pbEncoded, pcbEncoded, bytesNeeded)))
3055 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3056 pbEncoded = *(BYTE **)pbEncoded;
3057 *pbEncoded++ = ASN_SEQUENCEOF;
3058 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
3059 &lenBytes);
3060 pbEncoded += lenBytes;
3061 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3063 size = bytesNeeded;
3064 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3065 usage->rgpszUsageIdentifier[i],
3066 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
3067 &size);
3068 if (ret)
3070 pbEncoded += size;
3071 bytesNeeded -= size;
3078 __EXCEPT_PAGE_FAULT
3080 SetLastError(STATUS_ACCESS_VIOLATION);
3081 ret = FALSE;
3083 __ENDTRY
3084 return ret;
3087 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
3088 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3089 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3091 BOOL ret;
3093 __TRY
3095 const CRL_ISSUING_DIST_POINT *point =
3096 (const CRL_ISSUING_DIST_POINT *)pvStructInfo;
3097 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3098 struct AsnConstructedItem constructed = { 0 };
3099 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3100 DWORD cItem = 0, cSwapped = 0;
3102 ret = TRUE;
3103 switch (point->DistPointName.dwDistPointNameChoice)
3105 case CRL_DIST_POINT_NO_NAME:
3106 /* do nothing */
3107 break;
3108 case CRL_DIST_POINT_FULL_NAME:
3109 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3110 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3111 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3112 constructed.tag = 0;
3113 constructed.pvStructInfo = &swapped[cSwapped];
3114 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3115 items[cItem].pvStructInfo = &constructed;
3116 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3117 cSwapped++;
3118 cItem++;
3119 break;
3120 default:
3121 SetLastError(E_INVALIDARG);
3122 ret = FALSE;
3124 if (ret && point->fOnlyContainsUserCerts)
3126 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3127 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3128 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3129 items[cItem].pvStructInfo = &swapped[cSwapped];
3130 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3131 cSwapped++;
3132 cItem++;
3134 if (ret && point->fOnlyContainsCACerts)
3136 swapped[cSwapped].tag = ASN_CONTEXT | 2;
3137 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3138 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3139 items[cItem].pvStructInfo = &swapped[cSwapped];
3140 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3141 cSwapped++;
3142 cItem++;
3144 if (ret && point->OnlySomeReasonFlags.cbData)
3146 swapped[cSwapped].tag = ASN_CONTEXT | 3;
3147 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3148 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3149 items[cItem].pvStructInfo = &swapped[cSwapped];
3150 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3151 cSwapped++;
3152 cItem++;
3154 if (ret && point->fIndirectCRL)
3156 swapped[cSwapped].tag = ASN_CONTEXT | 4;
3157 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
3158 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3159 items[cItem].pvStructInfo = &swapped[cSwapped];
3160 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3161 cSwapped++;
3162 cItem++;
3164 if (ret)
3165 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3166 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3168 __EXCEPT_PAGE_FAULT
3170 SetLastError(STATUS_ACCESS_VIOLATION);
3171 ret = FALSE;
3173 __ENDTRY
3174 return ret;
3177 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
3178 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3179 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3180 DWORD *pcbEncoded)
3182 BOOL ret;
3183 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3184 (const CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3185 struct AsnEncodeSequenceItem items[] = {
3186 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
3187 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
3190 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3191 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3192 pcbEncoded);
3193 return ret;
3196 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
3197 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3198 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3200 BOOL ret = FALSE;
3202 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
3204 SetLastError(E_INVALIDARG);
3205 return FALSE;
3208 __TRY
3210 const CMSG_SIGNER_INFO *info = (const CMSG_SIGNER_INFO *)pvStructInfo;
3212 if (!info->Issuer.cbData)
3213 SetLastError(E_INVALIDARG);
3214 else
3216 struct AsnEncodeSequenceItem items[7] = {
3217 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
3218 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
3219 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
3220 0 },
3222 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3223 DWORD cItem = 3, cSwapped = 0;
3225 if (info->AuthAttrs.cAttr)
3227 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3228 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
3229 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3230 items[cItem].pvStructInfo = &swapped[cSwapped];
3231 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3232 cSwapped++;
3233 cItem++;
3235 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
3236 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
3237 cItem++;
3238 items[cItem].pvStructInfo = &info->EncryptedHash;
3239 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
3240 cItem++;
3241 if (info->UnauthAttrs.cAttr)
3243 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
3244 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
3245 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3246 items[cItem].pvStructInfo = &swapped[cSwapped];
3247 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3248 cSwapped++;
3249 cItem++;
3251 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3252 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3255 __EXCEPT_PAGE_FAULT
3257 SetLastError(STATUS_ACCESS_VIOLATION);
3259 __ENDTRY
3260 return ret;
3263 BOOL CRYPT_AsnEncodePKCSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
3264 DWORD *pcbData)
3266 struct AsnEncodeSequenceItem items[7] = {
3267 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
3269 struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 };
3270 struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 };
3271 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3272 DWORD cItem = 1, cSwapped = 0;
3273 BOOL ret = TRUE;
3275 if (signedInfo->cSignerInfo)
3277 digestAlgorithmsSet.cItems = signedInfo->cSignerInfo;
3278 digestAlgorithmsSet.items = signedInfo->rgSignerInfo;
3279 digestAlgorithmsSet.itemSize = sizeof(CMSG_SIGNER_INFO);
3280 digestAlgorithmsSet.itemOffset =
3281 offsetof(CMSG_SIGNER_INFO, HashAlgorithm);
3282 digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
3283 items[cItem].pvStructInfo = &digestAlgorithmsSet;
3284 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3285 cItem++;
3287 items[cItem].pvStructInfo = &signedInfo->content;
3288 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal;
3289 cItem++;
3290 if (signedInfo->cCertEncoded)
3292 certSet.cItems = signedInfo->cCertEncoded;
3293 certSet.items = signedInfo->rgCertEncoded;
3294 certSet.itemSize = sizeof(CERT_BLOB);
3295 certSet.itemOffset = 0;
3296 certSet.encode = CRYPT_CopyEncodedBlob;
3297 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0;
3298 swapped[cSwapped].pvStructInfo = &certSet;
3299 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3300 items[cItem].pvStructInfo = &swapped[cSwapped];
3301 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3302 cSwapped++;
3303 cItem++;
3305 if (signedInfo->cCrlEncoded)
3307 crlSet.cItems = signedInfo->cCrlEncoded;
3308 crlSet.items = signedInfo->rgCrlEncoded;
3309 crlSet.itemSize = sizeof(CRL_BLOB);
3310 crlSet.itemOffset = 0;
3311 crlSet.encode = CRYPT_CopyEncodedBlob;
3312 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
3313 swapped[cSwapped].pvStructInfo = &crlSet;
3314 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3315 items[cItem].pvStructInfo = &swapped[cSwapped];
3316 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3317 cSwapped++;
3318 cItem++;
3320 if (ret && signedInfo->cSignerInfo)
3322 signerSet.cItems = signedInfo->cSignerInfo;
3323 signerSet.items = signedInfo->rgSignerInfo;
3324 signerSet.itemSize = sizeof(CMSG_SIGNER_INFO);
3325 signerSet.itemOffset = 0;
3326 signerSet.encode = CRYPT_AsnEncodePKCSSignerInfo;
3327 items[cItem].pvStructInfo = &signerSet;
3328 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3329 cItem++;
3331 if (ret)
3332 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
3333 items, cItem, 0, NULL, pvData, pcbData);
3335 return ret;
3338 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
3339 LPCSTR lpszStructType)
3341 CryptEncodeObjectExFunc encodeFunc = NULL;
3343 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3344 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3346 SetLastError(ERROR_FILE_NOT_FOUND);
3347 return NULL;
3350 if (!HIWORD(lpszStructType))
3352 switch (LOWORD(lpszStructType))
3354 case (WORD)X509_CERT:
3355 encodeFunc = CRYPT_AsnEncodeCert;
3356 break;
3357 case (WORD)X509_CERT_TO_BE_SIGNED:
3358 encodeFunc = CRYPT_AsnEncodeCertInfo;
3359 break;
3360 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
3361 encodeFunc = CRYPT_AsnEncodeCRLInfo;
3362 break;
3363 case (WORD)X509_EXTENSIONS:
3364 encodeFunc = CRYPT_AsnEncodeExtensions;
3365 break;
3366 case (WORD)X509_NAME_VALUE:
3367 encodeFunc = CRYPT_AsnEncodeNameValue;
3368 break;
3369 case (WORD)X509_NAME:
3370 encodeFunc = CRYPT_AsnEncodeName;
3371 break;
3372 case (WORD)X509_PUBLIC_KEY_INFO:
3373 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
3374 break;
3375 case (WORD)X509_AUTHORITY_KEY_ID:
3376 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3377 break;
3378 case (WORD)X509_ALTERNATE_NAME:
3379 encodeFunc = CRYPT_AsnEncodeAltName;
3380 break;
3381 case (WORD)X509_BASIC_CONSTRAINTS:
3382 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3383 break;
3384 case (WORD)X509_BASIC_CONSTRAINTS2:
3385 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3386 break;
3387 case (WORD)RSA_CSP_PUBLICKEYBLOB:
3388 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
3389 break;
3390 case (WORD)X509_UNICODE_NAME:
3391 encodeFunc = CRYPT_AsnEncodeUnicodeName;
3392 break;
3393 case (WORD)PKCS_CONTENT_INFO:
3394 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
3395 break;
3396 case (WORD)PKCS_ATTRIBUTE:
3397 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
3398 break;
3399 case (WORD)X509_UNICODE_NAME_VALUE:
3400 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
3401 break;
3402 case (WORD)X509_OCTET_STRING:
3403 encodeFunc = CRYPT_AsnEncodeOctets;
3404 break;
3405 case (WORD)X509_BITS:
3406 case (WORD)X509_KEY_USAGE:
3407 encodeFunc = CRYPT_AsnEncodeBits;
3408 break;
3409 case (WORD)X509_INTEGER:
3410 encodeFunc = CRYPT_AsnEncodeInt;
3411 break;
3412 case (WORD)X509_MULTI_BYTE_INTEGER:
3413 encodeFunc = CRYPT_AsnEncodeInteger;
3414 break;
3415 case (WORD)X509_MULTI_BYTE_UINT:
3416 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
3417 break;
3418 case (WORD)X509_ENUMERATED:
3419 encodeFunc = CRYPT_AsnEncodeEnumerated;
3420 break;
3421 case (WORD)X509_CHOICE_OF_TIME:
3422 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
3423 break;
3424 case (WORD)X509_AUTHORITY_KEY_ID2:
3425 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3426 break;
3427 case (WORD)X509_SEQUENCE_OF_ANY:
3428 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
3429 break;
3430 case (WORD)PKCS_UTC_TIME:
3431 encodeFunc = CRYPT_AsnEncodeUtcTime;
3432 break;
3433 case (WORD)X509_CRL_DIST_POINTS:
3434 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3435 break;
3436 case (WORD)X509_ENHANCED_KEY_USAGE:
3437 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3438 break;
3439 case (WORD)PKCS_ATTRIBUTES:
3440 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3441 break;
3442 case (WORD)X509_ISSUING_DIST_POINT:
3443 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3444 break;
3445 case (WORD)PKCS7_SIGNER_INFO:
3446 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
3447 break;
3450 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3451 encodeFunc = CRYPT_AsnEncodeExtensions;
3452 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3453 encodeFunc = CRYPT_AsnEncodeUtcTime;
3454 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
3455 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3456 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
3457 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3458 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3459 encodeFunc = CRYPT_AsnEncodeEnumerated;
3460 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3461 encodeFunc = CRYPT_AsnEncodeBits;
3462 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3463 encodeFunc = CRYPT_AsnEncodeOctets;
3464 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3465 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3466 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3467 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3468 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3469 encodeFunc = CRYPT_AsnEncodeAltName;
3470 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3471 encodeFunc = CRYPT_AsnEncodeAltName;
3472 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3473 encodeFunc = CRYPT_AsnEncodeAltName;
3474 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3475 encodeFunc = CRYPT_AsnEncodeAltName;
3476 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3477 encodeFunc = CRYPT_AsnEncodeAltName;
3478 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3479 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3480 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3481 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3482 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3483 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3484 return encodeFunc;
3487 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType,
3488 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
3490 static HCRYPTOIDFUNCSET set = NULL;
3491 CryptEncodeObjectFunc encodeFunc = NULL;
3493 if (!set)
3494 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
3495 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3496 (void **)&encodeFunc, hFunc);
3497 return encodeFunc;
3500 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType,
3501 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
3503 static HCRYPTOIDFUNCSET set = NULL;
3504 CryptEncodeObjectExFunc encodeFunc = NULL;
3506 if (!set)
3507 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
3508 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3509 (void **)&encodeFunc, hFunc);
3510 return encodeFunc;
3513 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3514 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
3516 BOOL ret = FALSE;
3517 HCRYPTOIDFUNCADDR hFunc = NULL;
3518 CryptEncodeObjectFunc pCryptEncodeObject = NULL;
3519 CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL;
3521 TRACE_(crypt)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
3522 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
3523 pcbEncoded);
3525 if (!pbEncoded && !pcbEncoded)
3527 SetLastError(ERROR_INVALID_PARAMETER);
3528 return FALSE;
3531 if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType,
3532 lpszStructType)))
3534 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
3535 debugstr_a(lpszStructType));
3536 pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType,
3537 lpszStructType, &hFunc);
3538 if (!pCryptEncodeObject)
3539 pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType,
3540 lpszStructType, &hFunc);
3542 if (pCryptEncodeObject)
3543 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3544 pvStructInfo, pbEncoded, pcbEncoded);
3545 else if (pCryptEncodeObjectEx)
3546 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
3547 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
3548 if (hFunc)
3549 CryptFreeOIDFunctionAddress(hFunc, 0);
3550 TRACE_(crypt)("returning %d\n", ret);
3551 return ret;
3554 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3555 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
3556 void *pvEncoded, DWORD *pcbEncoded)
3558 BOOL ret = FALSE;
3559 HCRYPTOIDFUNCADDR hFunc = NULL;
3560 CryptEncodeObjectExFunc encodeFunc = NULL;
3562 TRACE_(crypt)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
3563 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
3564 pvEncoded, pcbEncoded);
3566 if (!pvEncoded && !pcbEncoded)
3568 SetLastError(ERROR_INVALID_PARAMETER);
3569 return FALSE;
3572 SetLastError(NOERROR);
3573 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
3574 *(BYTE **)pvEncoded = NULL;
3575 encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType);
3576 if (!encodeFunc)
3578 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
3579 debugstr_a(lpszStructType));
3580 encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType,
3581 &hFunc);
3583 if (encodeFunc)
3584 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
3585 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
3586 else
3588 CryptEncodeObjectFunc pCryptEncodeObject =
3589 CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
3591 if (pCryptEncodeObject)
3593 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3595 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3596 pvStructInfo, NULL, pcbEncoded);
3597 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3598 pvEncoded, pcbEncoded, *pcbEncoded)))
3599 ret = pCryptEncodeObject(dwCertEncodingType,
3600 lpszStructType, pvStructInfo, *(BYTE **)pvEncoded,
3601 pcbEncoded);
3603 else
3604 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3605 pvStructInfo, pvEncoded, pcbEncoded);
3608 if (hFunc)
3609 CryptFreeOIDFunctionAddress(hFunc, 0);
3610 TRACE_(crypt)("returning %d\n", ret);
3611 return ret;
3614 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
3615 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3617 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
3618 NULL, 0, NULL, pInfo, pcbInfo);
3621 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
3622 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3623 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3625 BOOL ret;
3626 HCRYPTKEY key;
3627 static CHAR oid[] = szOID_RSA_RSA;
3629 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv,
3630 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
3631 pvAuxInfo, pInfo, pcbInfo);
3633 if (!pszPublicKeyObjId)
3634 pszPublicKeyObjId = oid;
3635 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
3637 DWORD keySize = 0;
3639 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
3640 if (ret)
3642 LPBYTE pubKey = CryptMemAlloc(keySize);
3644 if (pubKey)
3646 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
3647 &keySize);
3648 if (ret)
3650 DWORD encodedLen = 0;
3652 ret = CryptEncodeObject(dwCertEncodingType,
3653 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
3654 if (ret)
3656 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
3657 strlen(pszPublicKeyObjId) + 1 + encodedLen;
3659 if (!pInfo)
3660 *pcbInfo = sizeNeeded;
3661 else if (*pcbInfo < sizeNeeded)
3663 SetLastError(ERROR_MORE_DATA);
3664 *pcbInfo = sizeNeeded;
3665 ret = FALSE;
3667 else
3669 pInfo->Algorithm.pszObjId = (char *)pInfo +
3670 sizeof(CERT_PUBLIC_KEY_INFO);
3671 lstrcpyA(pInfo->Algorithm.pszObjId,
3672 pszPublicKeyObjId);
3673 pInfo->Algorithm.Parameters.cbData = 0;
3674 pInfo->Algorithm.Parameters.pbData = NULL;
3675 pInfo->PublicKey.pbData =
3676 (BYTE *)pInfo->Algorithm.pszObjId
3677 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
3678 pInfo->PublicKey.cbData = encodedLen;
3679 pInfo->PublicKey.cUnusedBits = 0;
3680 ret = CryptEncodeObject(dwCertEncodingType,
3681 RSA_CSP_PUBLICKEYBLOB, pubKey,
3682 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
3686 CryptMemFree(pubKey);
3688 else
3689 ret = FALSE;
3691 CryptDestroyKey(key);
3693 return ret;
3696 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
3697 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3698 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
3700 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
3701 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
3702 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3704 static HCRYPTOIDFUNCSET set = NULL;
3705 BOOL ret;
3706 ExportPublicKeyInfoExFunc exportFunc = NULL;
3707 HCRYPTOIDFUNCADDR hFunc = NULL;
3709 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv,
3710 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
3711 pvAuxInfo, pInfo, pcbInfo);
3713 if (!hCryptProv)
3715 SetLastError(ERROR_INVALID_PARAMETER);
3716 return FALSE;
3719 if (pszPublicKeyObjId)
3721 if (!set)
3722 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
3724 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
3725 0, (void **)&exportFunc, &hFunc);
3727 if (!exportFunc)
3728 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
3729 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
3730 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
3731 if (hFunc)
3732 CryptFreeOIDFunctionAddress(hFunc, 0);
3733 return ret;
3736 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
3737 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
3739 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
3740 0, 0, NULL, phKey);
3743 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3744 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3745 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3747 BOOL ret;
3748 DWORD pubKeySize = 0;
3750 TRACE_(crypt)("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv,
3751 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3753 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3754 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
3755 if (ret)
3757 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
3759 if (pubKey)
3761 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3762 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
3763 &pubKeySize);
3764 if (ret)
3765 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
3766 phKey);
3767 CryptMemFree(pubKey);
3769 else
3770 ret = FALSE;
3772 return ret;
3775 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
3776 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3777 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
3779 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3780 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3781 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3783 static HCRYPTOIDFUNCSET set = NULL;
3784 BOOL ret;
3785 ImportPublicKeyInfoExFunc importFunc = NULL;
3786 HCRYPTOIDFUNCADDR hFunc = NULL;
3788 TRACE_(crypt)("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv,
3789 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3791 if (!set)
3792 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
3793 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
3794 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
3795 if (!importFunc)
3796 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
3797 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
3798 pvAuxInfo, phKey);
3799 if (hFunc)
3800 CryptFreeOIDFunctionAddress(hFunc, 0);
3801 return ret;