crypt32: Keep signer handle count separate from signer info.
[wine/multimedia.git] / dlls / crypt32 / encode.c
blobfc55d983387d27dc8d229330b3ecbf4886dcea41
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 WINAPI CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType,
1903 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1904 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1906 const CERT_ALT_NAME_ENTRY *entry =
1907 (const CERT_ALT_NAME_ENTRY *)pvStructInfo;
1908 BOOL ret;
1909 DWORD dataLen;
1910 BYTE tag;
1912 ret = TRUE;
1913 switch (entry->dwAltNameChoice)
1915 case CERT_ALT_NAME_RFC822_NAME:
1916 case CERT_ALT_NAME_DNS_NAME:
1917 case CERT_ALT_NAME_URL:
1918 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1919 if (entry->u.pwszURL)
1921 DWORD i;
1923 /* Not + 1: don't encode the NULL-terminator */
1924 dataLen = lstrlenW(entry->u.pwszURL);
1925 for (i = 0; ret && i < dataLen; i++)
1927 if (entry->u.pwszURL[i] > 0x7f)
1929 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1930 ret = FALSE;
1931 *pcbEncoded = i;
1935 else
1936 dataLen = 0;
1937 break;
1938 case CERT_ALT_NAME_DIRECTORY_NAME:
1939 tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1);
1940 dataLen = entry->u.DirectoryName.cbData;
1941 break;
1942 case CERT_ALT_NAME_IP_ADDRESS:
1943 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1944 dataLen = entry->u.IPAddress.cbData;
1945 break;
1946 case CERT_ALT_NAME_REGISTERED_ID:
1948 struct AsnEncodeTagSwappedItem swapped =
1949 { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID,
1950 CRYPT_AsnEncodeOid };
1952 return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded,
1953 pcbEncoded);
1955 case CERT_ALT_NAME_OTHER_NAME:
1956 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
1957 return FALSE;
1958 default:
1959 SetLastError(E_INVALIDARG);
1960 return FALSE;
1962 if (ret)
1964 DWORD bytesNeeded, lenBytes;
1966 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1967 bytesNeeded = 1 + dataLen + lenBytes;
1968 if (!pbEncoded)
1969 *pcbEncoded = bytesNeeded;
1970 else if (*pcbEncoded < bytesNeeded)
1972 SetLastError(ERROR_MORE_DATA);
1973 *pcbEncoded = bytesNeeded;
1974 ret = FALSE;
1976 else
1978 *pbEncoded++ = tag;
1979 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1980 pbEncoded += lenBytes;
1981 switch (entry->dwAltNameChoice)
1983 case CERT_ALT_NAME_RFC822_NAME:
1984 case CERT_ALT_NAME_DNS_NAME:
1985 case CERT_ALT_NAME_URL:
1987 DWORD i;
1989 for (i = 0; i < dataLen; i++)
1990 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
1991 break;
1993 case CERT_ALT_NAME_DIRECTORY_NAME:
1994 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen);
1995 break;
1996 case CERT_ALT_NAME_IP_ADDRESS:
1997 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
1998 break;
2000 if (ret)
2001 *pcbEncoded = bytesNeeded;
2004 TRACE("returning %d (%08x)\n", ret, GetLastError());
2005 return ret;
2008 static BOOL WINAPI CRYPT_AsnEncodeIntegerSwapBytes(DWORD dwCertEncodingType,
2009 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2010 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2012 BOOL ret;
2014 __TRY
2016 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2017 CRYPT_DATA_BLOB newBlob = { blob->cbData, NULL };
2019 ret = TRUE;
2020 if (newBlob.cbData)
2022 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2023 if (newBlob.pbData)
2025 DWORD i;
2027 for (i = 0; i < newBlob.cbData; i++)
2028 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2030 else
2031 ret = FALSE;
2033 if (ret)
2034 ret = CRYPT_AsnEncodeInteger(dwCertEncodingType, lpszStructType,
2035 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2036 CryptMemFree(newBlob.pbData);
2038 __EXCEPT_PAGE_FAULT
2040 SetLastError(STATUS_ACCESS_VIOLATION);
2041 ret = FALSE;
2043 __ENDTRY
2044 return ret;
2047 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
2048 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2049 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2051 BOOL ret;
2053 __TRY
2055 const CERT_AUTHORITY_KEY_ID_INFO *info =
2056 (const CERT_AUTHORITY_KEY_ID_INFO *)pvStructInfo;
2057 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2058 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2059 struct AsnConstructedItem constructed = { 0 };
2060 DWORD cItem = 0, cSwapped = 0;
2062 if (info->KeyId.cbData)
2064 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2065 swapped[cSwapped].pvStructInfo = &info->KeyId;
2066 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2067 items[cItem].pvStructInfo = &swapped[cSwapped];
2068 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2069 cSwapped++;
2070 cItem++;
2072 if (info->CertIssuer.cbData)
2074 constructed.tag = 1;
2075 constructed.pvStructInfo = &info->CertIssuer;
2076 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2077 items[cItem].pvStructInfo = &constructed;
2078 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2079 cItem++;
2081 if (info->CertSerialNumber.cbData)
2083 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2084 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2085 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2086 items[cItem].pvStructInfo = &swapped[cSwapped];
2087 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2088 cSwapped++;
2089 cItem++;
2091 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2092 pEncodePara, pbEncoded, pcbEncoded);
2094 __EXCEPT_PAGE_FAULT
2096 SetLastError(STATUS_ACCESS_VIOLATION);
2097 ret = FALSE;
2099 __ENDTRY
2100 return ret;
2103 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2104 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2105 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2107 BOOL ret;
2109 __TRY
2111 const CERT_ALT_NAME_INFO *info =
2112 (const CERT_ALT_NAME_INFO *)pvStructInfo;
2113 DWORD bytesNeeded, dataLen, lenBytes, i;
2115 ret = TRUE;
2116 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2117 * can't encode an erroneous entry index if it's bigger than this.
2119 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2121 DWORD len;
2123 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, NULL,
2124 &info->rgAltEntry[i], 0, NULL, NULL, &len);
2125 if (ret)
2126 dataLen += len;
2127 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2129 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2130 * the bad character, now set the index of the bad
2131 * entry
2133 *pcbEncoded = (BYTE)i <<
2134 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2137 if (ret)
2139 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2140 bytesNeeded = 1 + lenBytes + dataLen;
2141 if (!pbEncoded)
2143 *pcbEncoded = bytesNeeded;
2144 ret = TRUE;
2146 else
2148 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2149 pbEncoded, pcbEncoded, bytesNeeded)))
2151 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2152 pbEncoded = *(BYTE **)pbEncoded;
2153 *pbEncoded++ = ASN_SEQUENCEOF;
2154 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2155 pbEncoded += lenBytes;
2156 for (i = 0; ret && i < info->cAltEntry; i++)
2158 DWORD len = dataLen;
2160 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType,
2161 NULL, &info->rgAltEntry[i], 0, NULL, pbEncoded, &len);
2162 if (ret)
2164 pbEncoded += len;
2165 dataLen -= len;
2172 __EXCEPT_PAGE_FAULT
2174 SetLastError(STATUS_ACCESS_VIOLATION);
2175 ret = FALSE;
2177 __ENDTRY
2178 return ret;
2181 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2182 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2183 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2185 BOOL ret;
2187 __TRY
2189 const CERT_AUTHORITY_KEY_ID2_INFO *info =
2190 (const CERT_AUTHORITY_KEY_ID2_INFO *)pvStructInfo;
2191 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2192 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2193 DWORD cItem = 0, cSwapped = 0;
2195 if (info->KeyId.cbData)
2197 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2198 swapped[cSwapped].pvStructInfo = &info->KeyId;
2199 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2200 items[cItem].pvStructInfo = &swapped[cSwapped];
2201 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2202 cSwapped++;
2203 cItem++;
2205 if (info->AuthorityCertIssuer.cAltEntry)
2207 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2208 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2209 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2210 items[cItem].pvStructInfo = &swapped[cSwapped];
2211 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2212 cSwapped++;
2213 cItem++;
2215 if (info->AuthorityCertSerialNumber.cbData)
2217 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2218 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2219 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2220 items[cItem].pvStructInfo = &swapped[cSwapped];
2221 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2222 cSwapped++;
2223 cItem++;
2225 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2226 pEncodePara, pbEncoded, pcbEncoded);
2228 __EXCEPT_PAGE_FAULT
2230 SetLastError(STATUS_ACCESS_VIOLATION);
2231 ret = FALSE;
2233 __ENDTRY
2234 return ret;
2237 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2238 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2239 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2241 BOOL ret;
2243 __TRY
2245 const CERT_BASIC_CONSTRAINTS_INFO *info =
2246 (const CERT_BASIC_CONSTRAINTS_INFO *)pvStructInfo;
2247 struct AsnEncodeSequenceItem items[3] = {
2248 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2249 { 0 }
2251 DWORD cItem = 1;
2253 if (info->fPathLenConstraint)
2255 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2256 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2257 cItem++;
2259 if (info->cSubtreesConstraint)
2261 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2262 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2263 cItem++;
2265 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2266 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2268 __EXCEPT_PAGE_FAULT
2270 SetLastError(STATUS_ACCESS_VIOLATION);
2271 ret = FALSE;
2273 __ENDTRY
2274 return ret;
2277 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2278 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2279 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2281 BOOL ret;
2283 __TRY
2285 const CERT_BASIC_CONSTRAINTS2_INFO *info =
2286 (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
2287 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2288 DWORD cItem = 0;
2290 if (info->fCA)
2292 items[cItem].pvStructInfo = &info->fCA;
2293 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2294 cItem++;
2296 if (info->fPathLenConstraint)
2298 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2299 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2300 cItem++;
2302 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2303 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2305 __EXCEPT_PAGE_FAULT
2307 SetLastError(STATUS_ACCESS_VIOLATION);
2308 ret = FALSE;
2310 __ENDTRY
2311 return ret;
2314 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
2315 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2316 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2318 BOOL ret;
2320 __TRY
2322 const BLOBHEADER *hdr =
2323 (const BLOBHEADER *)pvStructInfo;
2325 if (hdr->bType != PUBLICKEYBLOB)
2327 SetLastError(E_INVALIDARG);
2328 ret = FALSE;
2330 else
2332 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
2333 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
2334 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
2335 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
2336 struct AsnEncodeSequenceItem items[] = {
2337 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
2338 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
2341 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2342 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
2343 pcbEncoded);
2346 __EXCEPT_PAGE_FAULT
2348 SetLastError(STATUS_ACCESS_VIOLATION);
2349 ret = FALSE;
2351 __ENDTRY
2352 return ret;
2355 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
2356 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2357 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2359 BOOL ret;
2361 __TRY
2363 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2364 DWORD bytesNeeded, lenBytes;
2366 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
2367 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
2369 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
2370 bytesNeeded = 1 + lenBytes + blob->cbData;
2371 if (!pbEncoded)
2373 *pcbEncoded = bytesNeeded;
2374 ret = TRUE;
2376 else
2378 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2379 pcbEncoded, bytesNeeded)))
2381 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2382 pbEncoded = *(BYTE **)pbEncoded;
2383 *pbEncoded++ = ASN_OCTETSTRING;
2384 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
2385 pbEncoded += lenBytes;
2386 if (blob->cbData)
2387 memcpy(pbEncoded, blob->pbData, blob->cbData);
2391 __EXCEPT_PAGE_FAULT
2393 SetLastError(STATUS_ACCESS_VIOLATION);
2394 ret = FALSE;
2396 __ENDTRY
2397 TRACE("returning %d (%08x)\n", ret, GetLastError());
2398 return ret;
2401 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
2402 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2403 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2405 BOOL ret;
2407 __TRY
2409 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2410 DWORD bytesNeeded, lenBytes, dataBytes;
2411 BYTE unusedBits;
2413 /* yep, MS allows cUnusedBits to be >= 8 */
2414 if (!blob->cUnusedBits)
2416 dataBytes = blob->cbData;
2417 unusedBits = 0;
2419 else if (blob->cbData * 8 > blob->cUnusedBits)
2421 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
2422 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
2423 blob->cUnusedBits;
2425 else
2427 dataBytes = 0;
2428 unusedBits = 0;
2430 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
2431 bytesNeeded = 1 + lenBytes + dataBytes + 1;
2432 if (!pbEncoded)
2434 *pcbEncoded = bytesNeeded;
2435 ret = TRUE;
2437 else
2439 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2440 pcbEncoded, bytesNeeded)))
2442 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2443 pbEncoded = *(BYTE **)pbEncoded;
2444 *pbEncoded++ = ASN_BITSTRING;
2445 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
2446 pbEncoded += lenBytes;
2447 *pbEncoded++ = unusedBits;
2448 if (dataBytes)
2450 BYTE mask = 0xff << unusedBits;
2452 if (dataBytes > 1)
2454 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
2455 pbEncoded += dataBytes - 1;
2457 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
2462 __EXCEPT_PAGE_FAULT
2464 SetLastError(STATUS_ACCESS_VIOLATION);
2465 ret = FALSE;
2467 __ENDTRY
2468 return ret;
2471 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
2472 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2473 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2475 BOOL ret;
2477 __TRY
2479 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2480 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
2482 ret = TRUE;
2483 if (newBlob.cbData)
2485 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2486 if (newBlob.pbData)
2488 DWORD i;
2490 for (i = 0; i < newBlob.cbData; i++)
2491 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2493 else
2494 ret = FALSE;
2496 if (ret)
2497 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
2498 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2499 CryptMemFree(newBlob.pbData);
2501 __EXCEPT_PAGE_FAULT
2503 SetLastError(STATUS_ACCESS_VIOLATION);
2504 ret = FALSE;
2506 __ENDTRY
2507 return ret;
2510 BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
2511 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2512 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2514 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
2516 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
2517 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2520 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
2521 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2522 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2524 BOOL ret;
2526 __TRY
2528 DWORD significantBytes, lenBytes;
2529 BYTE padByte = 0, bytesNeeded;
2530 BOOL pad = FALSE;
2531 const CRYPT_INTEGER_BLOB *blob =
2532 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2534 significantBytes = blob->cbData;
2535 if (significantBytes)
2537 if (blob->pbData[significantBytes - 1] & 0x80)
2539 /* negative, lop off leading (little-endian) 0xffs */
2540 for (; significantBytes > 0 &&
2541 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
2543 if (blob->pbData[significantBytes - 1] < 0x80)
2545 padByte = 0xff;
2546 pad = TRUE;
2549 else
2551 /* positive, lop off leading (little-endian) zeroes */
2552 for (; significantBytes > 0 &&
2553 !blob->pbData[significantBytes - 1]; significantBytes--)
2555 if (significantBytes == 0)
2556 significantBytes = 1;
2557 if (blob->pbData[significantBytes - 1] > 0x7f)
2559 padByte = 0;
2560 pad = TRUE;
2564 if (pad)
2565 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2566 else
2567 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2568 bytesNeeded = 1 + lenBytes + significantBytes;
2569 if (pad)
2570 bytesNeeded++;
2571 if (!pbEncoded)
2573 *pcbEncoded = bytesNeeded;
2574 ret = TRUE;
2576 else
2578 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2579 pcbEncoded, bytesNeeded)))
2581 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2582 pbEncoded = *(BYTE **)pbEncoded;
2583 *pbEncoded++ = ASN_INTEGER;
2584 if (pad)
2586 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2587 pbEncoded += lenBytes;
2588 *pbEncoded++ = padByte;
2590 else
2592 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2593 pbEncoded += lenBytes;
2595 for (; significantBytes > 0; significantBytes--)
2596 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2600 __EXCEPT_PAGE_FAULT
2602 SetLastError(STATUS_ACCESS_VIOLATION);
2603 ret = FALSE;
2605 __ENDTRY
2606 return ret;
2609 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
2610 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2611 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2613 BOOL ret;
2615 __TRY
2617 DWORD significantBytes, lenBytes;
2618 BYTE bytesNeeded;
2619 BOOL pad = FALSE;
2620 const CRYPT_INTEGER_BLOB *blob =
2621 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2623 significantBytes = blob->cbData;
2624 if (significantBytes)
2626 /* positive, lop off leading (little-endian) zeroes */
2627 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
2628 significantBytes--)
2630 if (significantBytes == 0)
2631 significantBytes = 1;
2632 if (blob->pbData[significantBytes - 1] > 0x7f)
2633 pad = TRUE;
2635 if (pad)
2636 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2637 else
2638 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2639 bytesNeeded = 1 + lenBytes + significantBytes;
2640 if (pad)
2641 bytesNeeded++;
2642 if (!pbEncoded)
2644 *pcbEncoded = bytesNeeded;
2645 ret = TRUE;
2647 else
2649 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2650 pcbEncoded, bytesNeeded)))
2652 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2653 pbEncoded = *(BYTE **)pbEncoded;
2654 *pbEncoded++ = ASN_INTEGER;
2655 if (pad)
2657 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2658 pbEncoded += lenBytes;
2659 *pbEncoded++ = 0;
2661 else
2663 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2664 pbEncoded += lenBytes;
2666 for (; significantBytes > 0; significantBytes--)
2667 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2671 __EXCEPT_PAGE_FAULT
2673 SetLastError(STATUS_ACCESS_VIOLATION);
2674 ret = FALSE;
2676 __ENDTRY
2677 return ret;
2680 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
2681 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2682 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2684 CRYPT_INTEGER_BLOB blob;
2685 BOOL ret;
2687 /* Encode as an unsigned integer, then change the tag to enumerated */
2688 blob.cbData = sizeof(DWORD);
2689 blob.pbData = (BYTE *)pvStructInfo;
2690 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
2691 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2692 if (ret && pbEncoded)
2694 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2695 pbEncoded = *(BYTE **)pbEncoded;
2696 pbEncoded[0] = ASN_ENUMERATED;
2698 return ret;
2701 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
2702 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2703 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2705 BOOL ret;
2707 __TRY
2709 SYSTEMTIME sysTime;
2710 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2711 * temporary buffer because the output buffer is not NULL-terminated.
2713 char buf[16];
2714 static const DWORD bytesNeeded = sizeof(buf) - 1;
2716 if (!pbEncoded)
2718 *pcbEncoded = bytesNeeded;
2719 ret = TRUE;
2721 else
2723 /* Sanity check the year, this is a two-digit year format */
2724 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2725 &sysTime);
2726 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
2728 SetLastError(CRYPT_E_BAD_ENCODE);
2729 ret = FALSE;
2731 if (ret)
2733 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2734 pbEncoded, pcbEncoded, bytesNeeded)))
2736 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2737 pbEncoded = *(BYTE **)pbEncoded;
2738 buf[0] = ASN_UTCTIME;
2739 buf[1] = bytesNeeded - 2;
2740 snprintf(buf + 2, sizeof(buf) - 2,
2741 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
2742 sysTime.wYear - 2000 : sysTime.wYear - 1900,
2743 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2744 sysTime.wMinute, sysTime.wSecond);
2745 memcpy(pbEncoded, buf, bytesNeeded);
2750 __EXCEPT_PAGE_FAULT
2752 SetLastError(STATUS_ACCESS_VIOLATION);
2753 ret = FALSE;
2755 __ENDTRY
2756 return ret;
2759 static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
2760 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2761 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2763 BOOL ret;
2765 __TRY
2767 SYSTEMTIME sysTime;
2768 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2769 * temporary buffer because the output buffer is not NULL-terminated.
2771 char buf[18];
2772 static const DWORD bytesNeeded = sizeof(buf) - 1;
2774 if (!pbEncoded)
2776 *pcbEncoded = bytesNeeded;
2777 ret = TRUE;
2779 else
2781 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2782 &sysTime);
2783 if (ret)
2784 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2785 pcbEncoded, bytesNeeded);
2786 if (ret)
2788 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2789 pbEncoded = *(BYTE **)pbEncoded;
2790 buf[0] = ASN_GENERALTIME;
2791 buf[1] = bytesNeeded - 2;
2792 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
2793 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2794 sysTime.wMinute, sysTime.wSecond);
2795 memcpy(pbEncoded, buf, bytesNeeded);
2799 __EXCEPT_PAGE_FAULT
2801 SetLastError(STATUS_ACCESS_VIOLATION);
2802 ret = FALSE;
2804 __ENDTRY
2805 return ret;
2808 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
2809 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2810 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2812 BOOL ret;
2814 __TRY
2816 SYSTEMTIME sysTime;
2818 /* Check the year, if it's in the UTCTime range call that encode func */
2819 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
2820 return FALSE;
2821 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
2822 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
2823 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2824 else
2825 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
2826 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
2827 pcbEncoded);
2829 __EXCEPT_PAGE_FAULT
2831 SetLastError(STATUS_ACCESS_VIOLATION);
2832 ret = FALSE;
2834 __ENDTRY
2835 return ret;
2838 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
2839 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2840 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2842 BOOL ret;
2844 __TRY
2846 DWORD bytesNeeded, dataLen, lenBytes, i;
2847 const CRYPT_SEQUENCE_OF_ANY *seq =
2848 (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2850 for (i = 0, dataLen = 0; i < seq->cValue; i++)
2851 dataLen += seq->rgValue[i].cbData;
2852 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2853 bytesNeeded = 1 + lenBytes + dataLen;
2854 if (!pbEncoded)
2856 *pcbEncoded = bytesNeeded;
2857 ret = TRUE;
2859 else
2861 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2862 pcbEncoded, bytesNeeded)))
2864 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2865 pbEncoded = *(BYTE **)pbEncoded;
2866 *pbEncoded++ = ASN_SEQUENCEOF;
2867 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2868 pbEncoded += lenBytes;
2869 for (i = 0; i < seq->cValue; i++)
2871 memcpy(pbEncoded, seq->rgValue[i].pbData,
2872 seq->rgValue[i].cbData);
2873 pbEncoded += seq->rgValue[i].cbData;
2878 __EXCEPT_PAGE_FAULT
2880 SetLastError(STATUS_ACCESS_VIOLATION);
2881 ret = FALSE;
2883 __ENDTRY
2884 return ret;
2887 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
2888 BYTE *pbEncoded, DWORD *pcbEncoded)
2890 BOOL ret = TRUE;
2891 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2892 struct AsnConstructedItem constructed = { 0 };
2893 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2894 DWORD cItem = 0, cSwapped = 0;
2896 switch (distPoint->DistPointName.dwDistPointNameChoice)
2898 case CRL_DIST_POINT_NO_NAME:
2899 /* do nothing */
2900 break;
2901 case CRL_DIST_POINT_FULL_NAME:
2902 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
2903 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
2904 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2905 constructed.tag = 0;
2906 constructed.pvStructInfo = &swapped[cSwapped];
2907 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
2908 items[cItem].pvStructInfo = &constructed;
2909 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2910 cSwapped++;
2911 cItem++;
2912 break;
2913 case CRL_DIST_POINT_ISSUER_RDN_NAME:
2914 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2915 ret = FALSE;
2916 break;
2917 default:
2918 ret = FALSE;
2920 if (ret && distPoint->ReasonFlags.cbData)
2922 swapped[cSwapped].tag = ASN_CONTEXT | 1;
2923 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
2924 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
2925 items[cItem].pvStructInfo = &swapped[cSwapped];
2926 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2927 cSwapped++;
2928 cItem++;
2930 if (ret && distPoint->CRLIssuer.cAltEntry)
2932 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
2933 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
2934 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2935 items[cItem].pvStructInfo = &swapped[cSwapped];
2936 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2937 cSwapped++;
2938 cItem++;
2940 if (ret)
2941 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
2942 pbEncoded, pcbEncoded);
2943 return ret;
2946 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
2947 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2948 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2950 BOOL ret;
2952 __TRY
2954 const CRL_DIST_POINTS_INFO *info =
2955 (const CRL_DIST_POINTS_INFO *)pvStructInfo;
2957 if (!info->cDistPoint)
2959 SetLastError(E_INVALIDARG);
2960 ret = FALSE;
2962 else
2964 DWORD bytesNeeded, dataLen, lenBytes, i;
2966 ret = TRUE;
2967 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
2969 DWORD len;
2971 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
2972 &len);
2973 if (ret)
2974 dataLen += len;
2975 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2977 /* Have to propagate index of failing character */
2978 *pcbEncoded = len;
2981 if (ret)
2983 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2984 bytesNeeded = 1 + lenBytes + dataLen;
2985 if (!pbEncoded)
2987 *pcbEncoded = bytesNeeded;
2988 ret = TRUE;
2990 else
2992 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2993 pbEncoded, pcbEncoded, bytesNeeded)))
2995 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2996 pbEncoded = *(BYTE **)pbEncoded;
2997 *pbEncoded++ = ASN_SEQUENCEOF;
2998 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2999 pbEncoded += lenBytes;
3000 for (i = 0; ret && i < info->cDistPoint; i++)
3002 DWORD len = dataLen;
3004 ret = CRYPT_AsnEncodeDistPoint(
3005 &info->rgDistPoint[i], pbEncoded, &len);
3006 if (ret)
3008 pbEncoded += len;
3009 dataLen -= len;
3017 __EXCEPT_PAGE_FAULT
3019 SetLastError(STATUS_ACCESS_VIOLATION);
3020 ret = FALSE;
3022 __ENDTRY
3023 return ret;
3026 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3027 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3028 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3030 BOOL ret;
3032 __TRY
3034 const CERT_ENHKEY_USAGE *usage =
3035 (const CERT_ENHKEY_USAGE *)pvStructInfo;
3036 DWORD bytesNeeded = 0, lenBytes, size, i;
3038 ret = TRUE;
3039 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3041 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3042 usage->rgpszUsageIdentifier[i],
3043 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
3044 if (ret)
3045 bytesNeeded += size;
3047 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3048 bytesNeeded += 1 + lenBytes;
3049 if (ret)
3051 if (!pbEncoded)
3052 *pcbEncoded = bytesNeeded;
3053 else
3055 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3056 pbEncoded, pcbEncoded, bytesNeeded)))
3058 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3059 pbEncoded = *(BYTE **)pbEncoded;
3060 *pbEncoded++ = ASN_SEQUENCEOF;
3061 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
3062 &lenBytes);
3063 pbEncoded += lenBytes;
3064 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3066 size = bytesNeeded;
3067 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3068 usage->rgpszUsageIdentifier[i],
3069 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
3070 &size);
3071 if (ret)
3073 pbEncoded += size;
3074 bytesNeeded -= size;
3081 __EXCEPT_PAGE_FAULT
3083 SetLastError(STATUS_ACCESS_VIOLATION);
3084 ret = FALSE;
3086 __ENDTRY
3087 return ret;
3090 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
3091 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3092 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3094 BOOL ret;
3096 __TRY
3098 const CRL_ISSUING_DIST_POINT *point =
3099 (const CRL_ISSUING_DIST_POINT *)pvStructInfo;
3100 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3101 struct AsnConstructedItem constructed = { 0 };
3102 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3103 DWORD cItem = 0, cSwapped = 0;
3105 ret = TRUE;
3106 switch (point->DistPointName.dwDistPointNameChoice)
3108 case CRL_DIST_POINT_NO_NAME:
3109 /* do nothing */
3110 break;
3111 case CRL_DIST_POINT_FULL_NAME:
3112 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3113 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3114 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3115 constructed.tag = 0;
3116 constructed.pvStructInfo = &swapped[cSwapped];
3117 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3118 items[cItem].pvStructInfo = &constructed;
3119 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3120 cSwapped++;
3121 cItem++;
3122 break;
3123 default:
3124 SetLastError(E_INVALIDARG);
3125 ret = FALSE;
3127 if (ret && point->fOnlyContainsUserCerts)
3129 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3130 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3131 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3132 items[cItem].pvStructInfo = &swapped[cSwapped];
3133 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3134 cSwapped++;
3135 cItem++;
3137 if (ret && point->fOnlyContainsCACerts)
3139 swapped[cSwapped].tag = ASN_CONTEXT | 2;
3140 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3141 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3142 items[cItem].pvStructInfo = &swapped[cSwapped];
3143 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3144 cSwapped++;
3145 cItem++;
3147 if (ret && point->OnlySomeReasonFlags.cbData)
3149 swapped[cSwapped].tag = ASN_CONTEXT | 3;
3150 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3151 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3152 items[cItem].pvStructInfo = &swapped[cSwapped];
3153 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3154 cSwapped++;
3155 cItem++;
3157 if (ret && point->fIndirectCRL)
3159 swapped[cSwapped].tag = ASN_CONTEXT | 4;
3160 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
3161 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3162 items[cItem].pvStructInfo = &swapped[cSwapped];
3163 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3164 cSwapped++;
3165 cItem++;
3167 if (ret)
3168 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3169 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3171 __EXCEPT_PAGE_FAULT
3173 SetLastError(STATUS_ACCESS_VIOLATION);
3174 ret = FALSE;
3176 __ENDTRY
3177 return ret;
3180 static BOOL WINAPI CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType,
3181 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3182 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3184 BOOL ret;
3185 const CERT_GENERAL_SUBTREE *subtree =
3186 (const CERT_GENERAL_SUBTREE *)pvStructInfo;
3187 struct AsnEncodeSequenceItem items[3] = {
3188 { &subtree->Base, CRYPT_AsnEncodeAltNameEntry, 0 },
3189 { 0 }
3191 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3192 DWORD cItem = 1, cSwapped = 0;
3194 if (subtree->dwMinimum)
3196 swapped[cSwapped].tag = ASN_CONTEXT | 0;
3197 swapped[cSwapped].pvStructInfo = &subtree->dwMinimum;
3198 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3199 items[cItem].pvStructInfo = &swapped[cSwapped];
3200 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3201 cSwapped++;
3202 cItem++;
3204 if (subtree->fMaximum)
3206 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3207 swapped[cSwapped].pvStructInfo = &subtree->dwMaximum;
3208 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3209 items[cItem].pvStructInfo = &swapped[cSwapped];
3210 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3211 cSwapped++;
3212 cItem++;
3214 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags,
3215 pEncodePara, pbEncoded, pcbEncoded);
3216 return ret;
3219 static BOOL WINAPI CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType,
3220 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3221 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3223 BOOL ret = FALSE;
3224 CRYPT_SET_OF permitted = { 0, NULL }, excluded = { 0, NULL };
3226 TRACE("%p\n", pvStructInfo);
3228 __TRY
3230 const CERT_NAME_CONSTRAINTS_INFO *constraints =
3231 (const CERT_NAME_CONSTRAINTS_INFO *)pvStructInfo;
3232 struct AsnEncodeSequenceItem items[2] = { { 0 } };
3233 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3234 DWORD i, cItem = 0, cSwapped = 0;
3236 ret = TRUE;
3237 if (constraints->cPermittedSubtree)
3239 permitted.rgValue = CryptMemAlloc(
3240 constraints->cPermittedSubtree * sizeof(CRYPT_DER_BLOB));
3241 if (permitted.rgValue)
3243 permitted.cValue = constraints->cPermittedSubtree;
3244 memset(permitted.rgValue, 0,
3245 permitted.cValue * sizeof(CRYPT_DER_BLOB));
3246 for (i = 0; ret && i < permitted.cValue; i++)
3247 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3248 NULL, &constraints->rgPermittedSubtree[i],
3249 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3250 (BYTE *)&permitted.rgValue[i].pbData,
3251 &permitted.rgValue[i].cbData);
3252 if (ret)
3254 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3255 swapped[cSwapped].pvStructInfo = &permitted;
3256 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3257 items[cItem].pvStructInfo = &swapped[cSwapped];
3258 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3259 cSwapped++;
3260 cItem++;
3263 else
3264 ret = FALSE;
3266 if (constraints->cExcludedSubtree)
3268 excluded.rgValue = CryptMemAlloc(
3269 constraints->cExcludedSubtree * sizeof(CRYPT_DER_BLOB));
3270 if (excluded.rgValue)
3272 excluded.cValue = constraints->cExcludedSubtree;
3273 memset(excluded.rgValue, 0,
3274 excluded.cValue * sizeof(CRYPT_DER_BLOB));
3275 for (i = 0; ret && i < excluded.cValue; i++)
3276 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3277 NULL, &constraints->rgExcludedSubtree[i],
3278 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3279 (BYTE *)&excluded.rgValue[i].pbData,
3280 &excluded.rgValue[i].cbData);
3281 if (ret)
3283 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
3284 swapped[cSwapped].pvStructInfo = &excluded;
3285 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3286 items[cItem].pvStructInfo = &swapped[cSwapped];
3287 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3288 cSwapped++;
3289 cItem++;
3292 else
3293 ret = FALSE;
3295 if (ret)
3296 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3297 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3298 for (i = 0; i < permitted.cValue; i++)
3299 LocalFree(permitted.rgValue[i].pbData);
3300 for (i = 0; i < excluded.cValue; i++)
3301 LocalFree(excluded.rgValue[i].pbData);
3303 __EXCEPT_PAGE_FAULT
3305 SetLastError(STATUS_ACCESS_VIOLATION);
3307 __ENDTRY
3308 CryptMemFree(permitted.rgValue);
3309 CryptMemFree(excluded.rgValue);
3310 TRACE("returning %d\n", ret);
3311 return ret;
3314 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
3315 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3316 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3317 DWORD *pcbEncoded)
3319 BOOL ret;
3320 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3321 (const CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3322 struct AsnEncodeSequenceItem items[] = {
3323 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
3324 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
3327 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3328 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3329 pcbEncoded);
3330 return ret;
3333 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
3334 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3335 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3337 BOOL ret = FALSE;
3339 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
3341 SetLastError(E_INVALIDARG);
3342 return FALSE;
3345 __TRY
3347 const CMSG_SIGNER_INFO *info = (const CMSG_SIGNER_INFO *)pvStructInfo;
3349 if (!info->Issuer.cbData)
3350 SetLastError(E_INVALIDARG);
3351 else
3353 struct AsnEncodeSequenceItem items[7] = {
3354 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
3355 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
3356 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
3357 0 },
3359 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3360 DWORD cItem = 3, cSwapped = 0;
3362 if (info->AuthAttrs.cAttr)
3364 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3365 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
3366 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3367 items[cItem].pvStructInfo = &swapped[cSwapped];
3368 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3369 cSwapped++;
3370 cItem++;
3372 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
3373 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
3374 cItem++;
3375 items[cItem].pvStructInfo = &info->EncryptedHash;
3376 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
3377 cItem++;
3378 if (info->UnauthAttrs.cAttr)
3380 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
3381 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
3382 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3383 items[cItem].pvStructInfo = &swapped[cSwapped];
3384 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3385 cSwapped++;
3386 cItem++;
3388 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3389 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3392 __EXCEPT_PAGE_FAULT
3394 SetLastError(STATUS_ACCESS_VIOLATION);
3396 __ENDTRY
3397 return ret;
3400 BOOL CRYPT_AsnEncodePKCSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
3401 DWORD *pcbData)
3403 struct AsnEncodeSequenceItem items[7] = {
3404 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
3406 struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 };
3407 struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 };
3408 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3409 DWORD cItem = 1, cSwapped = 0;
3410 BOOL ret = TRUE;
3412 if (signedInfo->cSignerInfo)
3414 digestAlgorithmsSet.cItems = signedInfo->cSignerInfo;
3415 digestAlgorithmsSet.items = signedInfo->rgSignerInfo;
3416 digestAlgorithmsSet.itemSize = sizeof(CMSG_SIGNER_INFO);
3417 digestAlgorithmsSet.itemOffset =
3418 offsetof(CMSG_SIGNER_INFO, HashAlgorithm);
3419 digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
3420 items[cItem].pvStructInfo = &digestAlgorithmsSet;
3421 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3422 cItem++;
3424 items[cItem].pvStructInfo = &signedInfo->content;
3425 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal;
3426 cItem++;
3427 if (signedInfo->cCertEncoded)
3429 certSet.cItems = signedInfo->cCertEncoded;
3430 certSet.items = signedInfo->rgCertEncoded;
3431 certSet.itemSize = sizeof(CERT_BLOB);
3432 certSet.itemOffset = 0;
3433 certSet.encode = CRYPT_CopyEncodedBlob;
3434 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0;
3435 swapped[cSwapped].pvStructInfo = &certSet;
3436 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3437 items[cItem].pvStructInfo = &swapped[cSwapped];
3438 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3439 cSwapped++;
3440 cItem++;
3442 if (signedInfo->cCrlEncoded)
3444 crlSet.cItems = signedInfo->cCrlEncoded;
3445 crlSet.items = signedInfo->rgCrlEncoded;
3446 crlSet.itemSize = sizeof(CRL_BLOB);
3447 crlSet.itemOffset = 0;
3448 crlSet.encode = CRYPT_CopyEncodedBlob;
3449 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
3450 swapped[cSwapped].pvStructInfo = &crlSet;
3451 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3452 items[cItem].pvStructInfo = &swapped[cSwapped];
3453 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3454 cSwapped++;
3455 cItem++;
3457 if (ret && signedInfo->cSignerInfo)
3459 signerSet.cItems = signedInfo->cSignerInfo;
3460 signerSet.items = signedInfo->rgSignerInfo;
3461 signerSet.itemSize = sizeof(CMSG_SIGNER_INFO);
3462 signerSet.itemOffset = 0;
3463 signerSet.encode = CRYPT_AsnEncodePKCSSignerInfo;
3464 items[cItem].pvStructInfo = &signerSet;
3465 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3466 cItem++;
3468 if (ret)
3469 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
3470 items, cItem, 0, NULL, pvData, pcbData);
3472 return ret;
3475 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
3476 LPCSTR lpszStructType)
3478 CryptEncodeObjectExFunc encodeFunc = NULL;
3480 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3481 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3483 SetLastError(ERROR_FILE_NOT_FOUND);
3484 return NULL;
3487 if (!HIWORD(lpszStructType))
3489 switch (LOWORD(lpszStructType))
3491 case LOWORD(X509_CERT):
3492 encodeFunc = CRYPT_AsnEncodeCert;
3493 break;
3494 case LOWORD(X509_CERT_TO_BE_SIGNED):
3495 encodeFunc = CRYPT_AsnEncodeCertInfo;
3496 break;
3497 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
3498 encodeFunc = CRYPT_AsnEncodeCRLInfo;
3499 break;
3500 case LOWORD(X509_EXTENSIONS):
3501 encodeFunc = CRYPT_AsnEncodeExtensions;
3502 break;
3503 case LOWORD(X509_NAME_VALUE):
3504 encodeFunc = CRYPT_AsnEncodeNameValue;
3505 break;
3506 case LOWORD(X509_NAME):
3507 encodeFunc = CRYPT_AsnEncodeName;
3508 break;
3509 case LOWORD(X509_PUBLIC_KEY_INFO):
3510 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
3511 break;
3512 case LOWORD(X509_AUTHORITY_KEY_ID):
3513 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3514 break;
3515 case LOWORD(X509_ALTERNATE_NAME):
3516 encodeFunc = CRYPT_AsnEncodeAltName;
3517 break;
3518 case LOWORD(X509_BASIC_CONSTRAINTS):
3519 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3520 break;
3521 case LOWORD(X509_BASIC_CONSTRAINTS2):
3522 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3523 break;
3524 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
3525 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
3526 break;
3527 case LOWORD(X509_UNICODE_NAME):
3528 encodeFunc = CRYPT_AsnEncodeUnicodeName;
3529 break;
3530 case LOWORD(PKCS_CONTENT_INFO):
3531 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
3532 break;
3533 case LOWORD(PKCS_ATTRIBUTE):
3534 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
3535 break;
3536 case LOWORD(X509_UNICODE_NAME_VALUE):
3537 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
3538 break;
3539 case LOWORD(X509_OCTET_STRING):
3540 encodeFunc = CRYPT_AsnEncodeOctets;
3541 break;
3542 case LOWORD(X509_BITS):
3543 case LOWORD(X509_KEY_USAGE):
3544 encodeFunc = CRYPT_AsnEncodeBits;
3545 break;
3546 case LOWORD(X509_INTEGER):
3547 encodeFunc = CRYPT_AsnEncodeInt;
3548 break;
3549 case LOWORD(X509_MULTI_BYTE_INTEGER):
3550 encodeFunc = CRYPT_AsnEncodeInteger;
3551 break;
3552 case LOWORD(X509_MULTI_BYTE_UINT):
3553 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
3554 break;
3555 case LOWORD(X509_ENUMERATED):
3556 encodeFunc = CRYPT_AsnEncodeEnumerated;
3557 break;
3558 case LOWORD(X509_CHOICE_OF_TIME):
3559 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
3560 break;
3561 case LOWORD(X509_AUTHORITY_KEY_ID2):
3562 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3563 break;
3564 case LOWORD(X509_SEQUENCE_OF_ANY):
3565 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
3566 break;
3567 case LOWORD(PKCS_UTC_TIME):
3568 encodeFunc = CRYPT_AsnEncodeUtcTime;
3569 break;
3570 case LOWORD(X509_CRL_DIST_POINTS):
3571 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3572 break;
3573 case LOWORD(X509_ENHANCED_KEY_USAGE):
3574 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3575 break;
3576 case LOWORD(PKCS_ATTRIBUTES):
3577 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3578 break;
3579 case LOWORD(X509_ISSUING_DIST_POINT):
3580 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3581 break;
3582 case LOWORD(X509_NAME_CONSTRAINTS):
3583 encodeFunc = CRYPT_AsnEncodeNameConstraints;
3584 break;
3585 case LOWORD(PKCS7_SIGNER_INFO):
3586 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
3587 break;
3590 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3591 encodeFunc = CRYPT_AsnEncodeExtensions;
3592 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3593 encodeFunc = CRYPT_AsnEncodeUtcTime;
3594 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
3595 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3596 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
3597 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3598 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3599 encodeFunc = CRYPT_AsnEncodeEnumerated;
3600 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3601 encodeFunc = CRYPT_AsnEncodeBits;
3602 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3603 encodeFunc = CRYPT_AsnEncodeOctets;
3604 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3605 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3606 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3607 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3608 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3609 encodeFunc = CRYPT_AsnEncodeAltName;
3610 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3611 encodeFunc = CRYPT_AsnEncodeAltName;
3612 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3613 encodeFunc = CRYPT_AsnEncodeAltName;
3614 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3615 encodeFunc = CRYPT_AsnEncodeAltName;
3616 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3617 encodeFunc = CRYPT_AsnEncodeAltName;
3618 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3619 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3620 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3621 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3622 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3623 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3624 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
3625 encodeFunc = CRYPT_AsnEncodeNameConstraints;
3626 return encodeFunc;
3629 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType,
3630 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
3632 static HCRYPTOIDFUNCSET set = NULL;
3633 CryptEncodeObjectFunc encodeFunc = NULL;
3635 if (!set)
3636 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
3637 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3638 (void **)&encodeFunc, hFunc);
3639 return encodeFunc;
3642 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType,
3643 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
3645 static HCRYPTOIDFUNCSET set = NULL;
3646 CryptEncodeObjectExFunc encodeFunc = NULL;
3648 if (!set)
3649 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
3650 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3651 (void **)&encodeFunc, hFunc);
3652 return encodeFunc;
3655 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3656 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
3658 BOOL ret = FALSE;
3659 HCRYPTOIDFUNCADDR hFunc = NULL;
3660 CryptEncodeObjectFunc pCryptEncodeObject = NULL;
3661 CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL;
3663 TRACE_(crypt)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
3664 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
3665 pcbEncoded);
3667 if (!pbEncoded && !pcbEncoded)
3669 SetLastError(ERROR_INVALID_PARAMETER);
3670 return FALSE;
3673 if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType,
3674 lpszStructType)))
3676 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
3677 debugstr_a(lpszStructType));
3678 pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType,
3679 lpszStructType, &hFunc);
3680 if (!pCryptEncodeObject)
3681 pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType,
3682 lpszStructType, &hFunc);
3684 if (pCryptEncodeObject)
3685 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3686 pvStructInfo, pbEncoded, pcbEncoded);
3687 else if (pCryptEncodeObjectEx)
3688 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
3689 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
3690 if (hFunc)
3691 CryptFreeOIDFunctionAddress(hFunc, 0);
3692 TRACE_(crypt)("returning %d\n", ret);
3693 return ret;
3696 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3697 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
3698 void *pvEncoded, DWORD *pcbEncoded)
3700 BOOL ret = FALSE;
3701 HCRYPTOIDFUNCADDR hFunc = NULL;
3702 CryptEncodeObjectExFunc encodeFunc = NULL;
3704 TRACE_(crypt)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
3705 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
3706 pvEncoded, pcbEncoded);
3708 if (!pvEncoded && !pcbEncoded)
3710 SetLastError(ERROR_INVALID_PARAMETER);
3711 return FALSE;
3714 SetLastError(NOERROR);
3715 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
3716 *(BYTE **)pvEncoded = NULL;
3717 encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType);
3718 if (!encodeFunc)
3720 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
3721 debugstr_a(lpszStructType));
3722 encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType,
3723 &hFunc);
3725 if (encodeFunc)
3726 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
3727 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
3728 else
3730 CryptEncodeObjectFunc pCryptEncodeObject =
3731 CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
3733 if (pCryptEncodeObject)
3735 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3737 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3738 pvStructInfo, NULL, pcbEncoded);
3739 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3740 pvEncoded, pcbEncoded, *pcbEncoded)))
3741 ret = pCryptEncodeObject(dwCertEncodingType,
3742 lpszStructType, pvStructInfo, *(BYTE **)pvEncoded,
3743 pcbEncoded);
3745 else
3746 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3747 pvStructInfo, pvEncoded, pcbEncoded);
3750 if (hFunc)
3751 CryptFreeOIDFunctionAddress(hFunc, 0);
3752 TRACE_(crypt)("returning %d\n", ret);
3753 return ret;
3756 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
3757 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3759 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
3760 NULL, 0, NULL, pInfo, pcbInfo);
3763 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
3764 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3765 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3767 BOOL ret;
3768 HCRYPTKEY key;
3769 static CHAR oid[] = szOID_RSA_RSA;
3771 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
3772 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
3773 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
3775 if (!pszPublicKeyObjId)
3776 pszPublicKeyObjId = oid;
3777 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
3779 DWORD keySize = 0;
3781 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
3782 if (ret)
3784 LPBYTE pubKey = CryptMemAlloc(keySize);
3786 if (pubKey)
3788 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
3789 &keySize);
3790 if (ret)
3792 DWORD encodedLen = 0;
3794 ret = CryptEncodeObject(dwCertEncodingType,
3795 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
3796 if (ret)
3798 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
3799 strlen(pszPublicKeyObjId) + 1 + encodedLen;
3801 if (!pInfo)
3802 *pcbInfo = sizeNeeded;
3803 else if (*pcbInfo < sizeNeeded)
3805 SetLastError(ERROR_MORE_DATA);
3806 *pcbInfo = sizeNeeded;
3807 ret = FALSE;
3809 else
3811 pInfo->Algorithm.pszObjId = (char *)pInfo +
3812 sizeof(CERT_PUBLIC_KEY_INFO);
3813 lstrcpyA(pInfo->Algorithm.pszObjId,
3814 pszPublicKeyObjId);
3815 pInfo->Algorithm.Parameters.cbData = 0;
3816 pInfo->Algorithm.Parameters.pbData = NULL;
3817 pInfo->PublicKey.pbData =
3818 (BYTE *)pInfo->Algorithm.pszObjId
3819 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
3820 pInfo->PublicKey.cbData = encodedLen;
3821 pInfo->PublicKey.cUnusedBits = 0;
3822 ret = CryptEncodeObject(dwCertEncodingType,
3823 RSA_CSP_PUBLICKEYBLOB, pubKey,
3824 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
3828 CryptMemFree(pubKey);
3830 else
3831 ret = FALSE;
3833 CryptDestroyKey(key);
3835 return ret;
3838 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
3839 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3840 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
3842 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
3843 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
3844 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3846 static HCRYPTOIDFUNCSET set = NULL;
3847 BOOL ret;
3848 ExportPublicKeyInfoExFunc exportFunc = NULL;
3849 HCRYPTOIDFUNCADDR hFunc = NULL;
3851 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
3852 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
3853 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
3855 if (!hCryptProv)
3857 SetLastError(ERROR_INVALID_PARAMETER);
3858 return FALSE;
3861 if (pszPublicKeyObjId)
3863 if (!set)
3864 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
3866 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
3867 0, (void **)&exportFunc, &hFunc);
3869 if (!exportFunc)
3870 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
3871 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
3872 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
3873 if (hFunc)
3874 CryptFreeOIDFunctionAddress(hFunc, 0);
3875 return ret;
3878 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
3879 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
3881 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
3882 0, 0, NULL, phKey);
3885 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3886 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3887 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3889 BOOL ret;
3890 DWORD pubKeySize = 0;
3892 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
3893 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3895 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3896 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
3897 if (ret)
3899 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
3901 if (pubKey)
3903 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3904 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
3905 &pubKeySize);
3906 if (ret)
3907 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
3908 phKey);
3909 CryptMemFree(pubKey);
3911 else
3912 ret = FALSE;
3914 return ret;
3917 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
3918 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3919 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
3921 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3922 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3923 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3925 static HCRYPTOIDFUNCSET set = NULL;
3926 BOOL ret;
3927 ImportPublicKeyInfoExFunc importFunc = NULL;
3928 HCRYPTOIDFUNCADDR hFunc = NULL;
3930 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
3931 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3933 if (!set)
3934 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
3935 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
3936 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
3937 if (!importFunc)
3938 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
3939 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
3940 pvAuxInfo, phKey);
3941 if (hFunc)
3942 CryptFreeOIDFunctionAddress(hFunc, 0);
3943 return ret;