urlmon: Remove 'recursive registry key delete' function.
[wine/multimedia.git] / dlls / crypt32 / encode.c
blob96e94f4a3b64c5322cf75a793ed65f0a21ba82c4
1 /*
2 * Copyright 2005 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 is
21 * undocumented, 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:
31 * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp
34 #include <assert.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <stdlib.h>
39 #define NONAMELESSUNION
41 #include "windef.h"
42 #include "winbase.h"
43 #include "wincrypt.h"
44 #include "snmp.h"
45 #include "wine/debug.h"
46 #include "wine/exception.h"
47 #include "wine/unicode.h"
48 #include "crypt32_private.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
51 WINE_DECLARE_DEBUG_CHANNEL(crypt);
53 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
54 BYTE *, DWORD *);
56 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
57 * The dwCertEncodingType and lpszStructType are ignored by the built-in
58 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
59 * since it must call functions in external DLLs that follow these signatures.
61 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
62 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
63 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
64 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
65 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
66 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
67 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
68 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
69 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
70 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
71 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
72 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
73 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
74 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
75 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
76 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
77 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
78 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
79 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
80 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
81 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
82 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
83 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
84 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
85 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
86 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
87 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
88 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
89 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
90 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
91 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
92 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
93 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
95 BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
96 BYTE *pbEncoded, DWORD *pcbEncoded, DWORD bytesNeeded)
98 BOOL ret = TRUE;
100 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
102 if (pEncodePara && pEncodePara->pfnAlloc)
103 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
104 else
105 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
106 if (!*(BYTE **)pbEncoded)
107 ret = FALSE;
108 else
109 *pcbEncoded = bytesNeeded;
111 else if (bytesNeeded > *pcbEncoded)
113 *pcbEncoded = bytesNeeded;
114 SetLastError(ERROR_MORE_DATA);
115 ret = FALSE;
117 else
118 *pcbEncoded = bytesNeeded;
119 return ret;
122 BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
124 DWORD bytesNeeded, significantBytes = 0;
126 if (len <= 0x7f)
127 bytesNeeded = 1;
128 else
130 DWORD temp;
132 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
133 temp <<= 8, significantBytes--)
135 bytesNeeded = significantBytes + 1;
137 if (!pbEncoded)
139 *pcbEncoded = bytesNeeded;
140 return TRUE;
142 if (*pcbEncoded < bytesNeeded)
144 SetLastError(ERROR_MORE_DATA);
145 return FALSE;
147 if (len <= 0x7f)
148 *pbEncoded = (BYTE)len;
149 else
151 DWORD i;
153 *pbEncoded++ = significantBytes | 0x80;
154 for (i = 0; i < significantBytes; i++)
156 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
157 len >>= 8;
160 *pcbEncoded = bytesNeeded;
161 return TRUE;
164 BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
165 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
166 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
168 BOOL ret;
169 DWORD i, dataLen = 0;
171 TRACE("%p, %d, %08x, %p, %p, %d\n", items, cItem, dwFlags, pEncodePara,
172 pbEncoded, *pcbEncoded);
173 for (i = 0, ret = TRUE; ret && i < cItem; i++)
175 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
176 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
177 NULL, &items[i].size);
178 /* Some functions propagate their errors through the size */
179 if (!ret)
180 *pcbEncoded = items[i].size;
181 dataLen += items[i].size;
183 if (ret)
185 DWORD lenBytes, bytesNeeded;
187 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
188 bytesNeeded = 1 + lenBytes + dataLen;
189 if (!pbEncoded)
190 *pcbEncoded = bytesNeeded;
191 else
193 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
194 pcbEncoded, bytesNeeded)))
196 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
197 pbEncoded = *(BYTE **)pbEncoded;
198 *pbEncoded++ = ASN_SEQUENCE;
199 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
200 pbEncoded += lenBytes;
201 for (i = 0; ret && i < cItem; i++)
203 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
204 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
205 NULL, pbEncoded, &items[i].size);
206 /* Some functions propagate their errors through the size */
207 if (!ret)
208 *pcbEncoded = items[i].size;
209 pbEncoded += items[i].size;
214 TRACE("returning %d (%08x)\n", ret, GetLastError());
215 return ret;
218 BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
219 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
220 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
222 BOOL ret;
223 const struct AsnConstructedItem *item =
224 (const struct AsnConstructedItem *)pvStructInfo;
225 DWORD len;
227 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
228 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
230 DWORD dataLen, bytesNeeded;
232 CRYPT_EncodeLen(len, NULL, &dataLen);
233 bytesNeeded = 1 + dataLen + len;
234 if (!pbEncoded)
235 *pcbEncoded = bytesNeeded;
236 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
237 pbEncoded, pcbEncoded, bytesNeeded)))
239 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
240 pbEncoded = *(BYTE **)pbEncoded;
241 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
242 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
243 pbEncoded += dataLen;
244 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
245 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
246 pbEncoded, &len);
247 if (!ret)
249 /* Some functions propagate their errors through the size */
250 *pcbEncoded = len;
254 else
256 /* Some functions propagate their errors through the size */
257 *pcbEncoded = len;
259 return ret;
262 struct AsnEncodeTagSwappedItem
264 BYTE tag;
265 const void *pvStructInfo;
266 CryptEncodeObjectExFunc encodeFunc;
269 /* Sort of a wacky hack, it encodes something using the struct
270 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
271 * given in the struct AsnEncodeTagSwappedItem.
273 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
274 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
275 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
277 BOOL ret;
278 const struct AsnEncodeTagSwappedItem *item =
279 (const struct AsnEncodeTagSwappedItem *)pvStructInfo;
281 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
282 item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
283 if (ret && pbEncoded)
284 *pbEncoded = item->tag;
285 return ret;
288 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
289 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
290 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
292 const DWORD *ver = (const DWORD *)pvStructInfo;
293 BOOL ret;
295 /* CERT_V1 is not encoded */
296 if (*ver == CERT_V1)
298 *pcbEncoded = 0;
299 ret = TRUE;
301 else
303 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
305 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
306 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
308 return ret;
311 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
312 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
313 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
315 const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
316 BOOL ret;
318 if (!pbEncoded)
320 *pcbEncoded = blob->cbData;
321 ret = TRUE;
323 else
325 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
326 pcbEncoded, blob->cbData)))
328 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
329 pbEncoded = *(BYTE **)pbEncoded;
330 if (blob->cbData)
331 memcpy(pbEncoded, blob->pbData, blob->cbData);
332 *pcbEncoded = blob->cbData;
333 ret = TRUE;
336 return ret;
339 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
340 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
341 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
343 BOOL ret;
344 /* This has two filetimes in a row, a NotBefore and a NotAfter */
345 const FILETIME *timePtr = (const FILETIME *)pvStructInfo;
346 struct AsnEncodeSequenceItem items[] = {
347 { timePtr++, CRYPT_AsnEncodeChoiceOfTime, 0 },
348 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
351 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
352 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
353 pcbEncoded);
354 return ret;
357 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
358 * if they are empty.
360 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
361 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
362 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
363 DWORD *pcbEncoded)
365 const CRYPT_ALGORITHM_IDENTIFIER *algo =
366 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
367 static const BYTE asn1Null[] = { ASN_NULL, 0 };
368 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
369 (LPBYTE)asn1Null };
370 BOOL ret;
371 struct AsnEncodeSequenceItem items[2] = {
372 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
373 { NULL, CRYPT_CopyEncodedBlob, 0 },
376 if (algo->Parameters.cbData)
377 items[1].pvStructInfo = &algo->Parameters;
378 else
379 items[1].pvStructInfo = &nullBlob;
380 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
381 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
382 pcbEncoded);
383 return ret;
386 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType,
387 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
388 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
390 const CRYPT_ALGORITHM_IDENTIFIER *algo =
391 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
392 BOOL ret;
393 struct AsnEncodeSequenceItem items[] = {
394 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
395 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
398 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
399 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
400 pcbEncoded);
401 return ret;
404 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
405 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
406 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
408 BOOL ret;
410 __TRY
412 const CERT_PUBLIC_KEY_INFO *info =
413 (const CERT_PUBLIC_KEY_INFO *)pvStructInfo;
414 struct AsnEncodeSequenceItem items[] = {
415 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
416 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
419 TRACE("Encoding public key with OID %s\n",
420 debugstr_a(info->Algorithm.pszObjId));
421 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
422 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
423 pcbEncoded);
425 __EXCEPT_PAGE_FAULT
427 SetLastError(STATUS_ACCESS_VIOLATION);
428 ret = FALSE;
430 __ENDTRY
431 return ret;
434 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
435 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
436 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
438 BOOL ret;
440 __TRY
442 const CERT_SIGNED_CONTENT_INFO *info =
443 (const CERT_SIGNED_CONTENT_INFO *)pvStructInfo;
444 struct AsnEncodeSequenceItem items[] = {
445 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
446 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
447 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
450 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
451 items[2].encodeFunc = CRYPT_AsnEncodeBits;
452 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
453 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
454 pcbEncoded);
456 __EXCEPT_PAGE_FAULT
458 SetLastError(STATUS_ACCESS_VIOLATION);
459 ret = FALSE;
461 __ENDTRY
462 return ret;
465 /* Like in Windows, this blithely ignores the validity of the passed-in
466 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
467 * decode properly, see CRYPT_AsnDecodeCertInfo.
469 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
470 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
471 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
473 BOOL ret;
475 __TRY
477 const CERT_INFO *info = (const CERT_INFO *)pvStructInfo;
478 struct AsnEncodeSequenceItem items[10] = {
479 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
480 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
481 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
482 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
483 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
484 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
485 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfo, 0 },
486 { 0 }
488 struct AsnConstructedItem constructed[3] = { { 0 } };
489 DWORD cItem = 7, cConstructed = 0;
491 if (info->IssuerUniqueId.cbData)
493 constructed[cConstructed].tag = 1;
494 constructed[cConstructed].pvStructInfo = &info->IssuerUniqueId;
495 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
496 items[cItem].pvStructInfo = &constructed[cConstructed];
497 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
498 cConstructed++;
499 cItem++;
501 if (info->SubjectUniqueId.cbData)
503 constructed[cConstructed].tag = 2;
504 constructed[cConstructed].pvStructInfo = &info->SubjectUniqueId;
505 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
506 items[cItem].pvStructInfo = &constructed[cConstructed];
507 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
508 cConstructed++;
509 cItem++;
511 if (info->cExtension)
513 constructed[cConstructed].tag = 3;
514 constructed[cConstructed].pvStructInfo = &info->cExtension;
515 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
516 items[cItem].pvStructInfo = &constructed[cConstructed];
517 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
518 cConstructed++;
519 cItem++;
522 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
523 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
525 __EXCEPT_PAGE_FAULT
527 SetLastError(STATUS_ACCESS_VIOLATION);
528 ret = FALSE;
530 __ENDTRY
531 return ret;
534 static BOOL WINAPI CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
535 BYTE *pbEncoded, DWORD *pcbEncoded)
537 struct AsnEncodeSequenceItem items[3] = {
538 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
539 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
540 { 0 }
542 DWORD cItem = 2;
543 BOOL ret;
545 TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded);
547 if (entry->cExtension)
549 items[cItem].pvStructInfo = &entry->cExtension;
550 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
551 cItem++;
554 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
555 pbEncoded, pcbEncoded);
557 TRACE("returning %d (%08x)\n", ret, GetLastError());
558 return ret;
561 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
562 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
563 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
565 DWORD cCRLEntry = *(const DWORD *)pvStructInfo;
566 DWORD bytesNeeded, dataLen, lenBytes, i;
567 const CRL_ENTRY *rgCRLEntry = *(const CRL_ENTRY *const *)
568 ((const BYTE *)pvStructInfo + sizeof(DWORD));
569 BOOL ret = TRUE;
571 for (i = 0, dataLen = 0; ret && i < cCRLEntry; i++)
573 DWORD size;
575 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
576 if (ret)
577 dataLen += size;
579 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
580 bytesNeeded = 1 + lenBytes + dataLen;
581 if (!pbEncoded)
582 *pcbEncoded = bytesNeeded;
583 else
585 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
586 pcbEncoded, bytesNeeded)))
588 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
589 pbEncoded = *(BYTE **)pbEncoded;
590 *pbEncoded++ = ASN_SEQUENCEOF;
591 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
592 pbEncoded += lenBytes;
593 for (i = 0; i < cCRLEntry; i++)
595 DWORD size = dataLen;
597 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], pbEncoded, &size);
598 pbEncoded += size;
599 dataLen -= size;
603 return ret;
606 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
607 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
608 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
610 const DWORD *ver = (const DWORD *)pvStructInfo;
611 BOOL ret;
613 /* CRL_V1 is not encoded */
614 if (*ver == CRL_V1)
616 *pcbEncoded = 0;
617 ret = TRUE;
619 else
620 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
621 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
622 return ret;
625 /* Like in Windows, this blithely ignores the validity of the passed-in
626 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
627 * decode properly, see CRYPT_AsnDecodeCRLInfo.
629 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
630 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
631 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
633 BOOL ret;
635 __TRY
637 const CRL_INFO *info = (const CRL_INFO *)pvStructInfo;
638 struct AsnEncodeSequenceItem items[7] = {
639 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
640 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
641 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
642 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
643 { 0 }
645 struct AsnConstructedItem constructed[1] = { { 0 } };
646 DWORD cItem = 4, cConstructed = 0;
648 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
650 items[cItem].pvStructInfo = &info->NextUpdate;
651 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
652 cItem++;
654 if (info->cCRLEntry)
656 items[cItem].pvStructInfo = &info->cCRLEntry;
657 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
658 cItem++;
660 if (info->cExtension)
662 constructed[cConstructed].tag = 0;
663 constructed[cConstructed].pvStructInfo = &info->cExtension;
664 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
665 items[cItem].pvStructInfo = &constructed[cConstructed];
666 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
667 cConstructed++;
668 cItem++;
671 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
672 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
674 __EXCEPT_PAGE_FAULT
676 SetLastError(STATUS_ACCESS_VIOLATION);
677 ret = FALSE;
679 __ENDTRY
680 return ret;
683 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
684 DWORD *pcbEncoded)
686 BOOL ret;
687 struct AsnEncodeSequenceItem items[3] = {
688 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
689 { NULL, NULL, 0 },
690 { NULL, NULL, 0 },
692 DWORD cItem = 1;
694 TRACE("%p, %p, %d\n", ext, pbEncoded, *pcbEncoded);
696 if (ext->fCritical)
698 items[cItem].pvStructInfo = &ext->fCritical;
699 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
700 cItem++;
702 items[cItem].pvStructInfo = &ext->Value;
703 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
704 cItem++;
706 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
707 pbEncoded, pcbEncoded);
708 TRACE("returning %d (%08x)\n", ret, GetLastError());
709 return ret;
712 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
713 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
714 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
716 BOOL ret;
718 __TRY
720 DWORD bytesNeeded, dataLen, lenBytes, i;
721 const CERT_EXTENSIONS *exts = (const CERT_EXTENSIONS *)pvStructInfo;
723 ret = TRUE;
724 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
726 DWORD size;
728 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
729 if (ret)
730 dataLen += size;
732 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
733 bytesNeeded = 1 + lenBytes + dataLen;
734 if (!pbEncoded)
735 *pcbEncoded = bytesNeeded;
736 else
738 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
739 pcbEncoded, bytesNeeded)))
741 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
742 pbEncoded = *(BYTE **)pbEncoded;
743 *pbEncoded++ = ASN_SEQUENCEOF;
744 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
745 pbEncoded += lenBytes;
746 for (i = 0; i < exts->cExtension; i++)
748 DWORD size = dataLen;
750 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
751 pbEncoded, &size);
752 pbEncoded += size;
753 dataLen -= size;
758 __EXCEPT_PAGE_FAULT
760 SetLastError(STATUS_ACCESS_VIOLATION);
761 ret = FALSE;
763 __ENDTRY
764 return ret;
767 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
768 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
769 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
771 LPCSTR pszObjId = (LPCSTR)pvStructInfo;
772 DWORD bytesNeeded = 0, lenBytes;
773 BOOL ret = TRUE;
774 int firstPos = 0;
775 BYTE firstByte = 0;
777 TRACE("%s\n", debugstr_a(pszObjId));
779 if (pszObjId)
781 const char *ptr;
782 int val1, val2;
784 if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
786 SetLastError(CRYPT_E_ASN1_ERROR);
787 return FALSE;
789 bytesNeeded++;
790 firstByte = val1 * 40 + val2;
791 ptr = pszObjId + firstPos;
792 while (ret && *ptr)
794 int pos;
796 /* note I assume each component is at most 32-bits long in base 2 */
797 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
799 if (val1 >= 0x10000000)
800 bytesNeeded += 5;
801 else if (val1 >= 0x200000)
802 bytesNeeded += 4;
803 else if (val1 >= 0x4000)
804 bytesNeeded += 3;
805 else if (val1 >= 0x80)
806 bytesNeeded += 2;
807 else
808 bytesNeeded += 1;
809 ptr += pos;
810 if (*ptr == '.')
811 ptr++;
813 else
815 SetLastError(CRYPT_E_ASN1_ERROR);
816 return FALSE;
819 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
821 else
822 lenBytes = 1;
823 bytesNeeded += 1 + lenBytes;
824 if (pbEncoded)
826 if (*pcbEncoded < bytesNeeded)
828 SetLastError(ERROR_MORE_DATA);
829 ret = FALSE;
831 else
833 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
834 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
835 pbEncoded += lenBytes;
836 if (pszObjId)
838 const char *ptr;
839 int val, pos;
841 *pbEncoded++ = firstByte;
842 ptr = pszObjId + firstPos;
843 while (ret && *ptr)
845 sscanf(ptr, "%d%n", &val, &pos);
847 unsigned char outBytes[5];
848 int numBytes, i;
850 if (val >= 0x10000000)
851 numBytes = 5;
852 else if (val >= 0x200000)
853 numBytes = 4;
854 else if (val >= 0x4000)
855 numBytes = 3;
856 else if (val >= 0x80)
857 numBytes = 2;
858 else
859 numBytes = 1;
860 for (i = numBytes; i > 0; i--)
862 outBytes[i - 1] = val & 0x7f;
863 val >>= 7;
865 for (i = 0; i < numBytes - 1; i++)
866 *pbEncoded++ = outBytes[i] | 0x80;
867 *pbEncoded++ = outBytes[i];
868 ptr += pos;
869 if (*ptr == '.')
870 ptr++;
876 *pcbEncoded = bytesNeeded;
877 return ret;
880 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
881 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
882 DWORD *pcbEncoded)
884 BOOL ret = TRUE;
885 LPCSTR str = (LPCSTR)value->Value.pbData;
886 DWORD bytesNeeded, lenBytes, encodedLen;
888 encodedLen = value->Value.cbData ? value->Value.cbData : lstrlenA(str);
889 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
890 bytesNeeded = 1 + lenBytes + encodedLen;
891 if (!pbEncoded)
892 *pcbEncoded = bytesNeeded;
893 else
895 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
896 pbEncoded, pcbEncoded, bytesNeeded)))
898 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
899 pbEncoded = *(BYTE **)pbEncoded;
900 *pbEncoded++ = tag;
901 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
902 pbEncoded += lenBytes;
903 memcpy(pbEncoded, str, encodedLen);
906 return ret;
909 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
910 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
911 DWORD *pcbEncoded)
913 BOOL ret = TRUE;
914 LPCWSTR str = (LPCWSTR)value->Value.pbData;
915 DWORD bytesNeeded, lenBytes, strLen;
917 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
918 lstrlenW(str);
919 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
920 bytesNeeded = 1 + lenBytes + strLen * 2;
921 if (!pbEncoded)
922 *pcbEncoded = bytesNeeded;
923 else
925 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
926 pbEncoded, pcbEncoded, bytesNeeded)))
928 DWORD i;
930 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
931 pbEncoded = *(BYTE **)pbEncoded;
932 *pbEncoded++ = ASN_BMPSTRING;
933 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
934 pbEncoded += lenBytes;
935 for (i = 0; i < strLen; i++)
937 *pbEncoded++ = (str[i] & 0xff00) >> 8;
938 *pbEncoded++ = str[i] & 0x00ff;
942 return ret;
945 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
946 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
947 DWORD *pcbEncoded)
949 BOOL ret = TRUE;
950 LPCWSTR str = (LPCWSTR)value->Value.pbData;
951 DWORD bytesNeeded, lenBytes, encodedLen, strLen;
953 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
954 lstrlenW(str);
955 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
956 NULL);
957 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
958 bytesNeeded = 1 + lenBytes + encodedLen;
959 if (!pbEncoded)
960 *pcbEncoded = bytesNeeded;
961 else
963 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
964 pbEncoded, pcbEncoded, bytesNeeded)))
966 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
967 pbEncoded = *(BYTE **)pbEncoded;
968 *pbEncoded++ = ASN_UTF8STRING;
969 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
970 pbEncoded += lenBytes;
971 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
972 bytesNeeded - lenBytes - 1, NULL, NULL);
975 return ret;
978 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
979 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
980 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
982 BOOL ret = TRUE;
984 __TRY
986 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
988 switch (value->dwValueType)
990 case CERT_RDN_ANY_TYPE:
991 /* explicitly disallowed */
992 SetLastError(E_INVALIDARG);
993 ret = FALSE;
994 break;
995 case CERT_RDN_ENCODED_BLOB:
996 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
997 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
998 break;
999 case CERT_RDN_OCTET_STRING:
1000 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1001 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1002 break;
1003 case CERT_RDN_NUMERIC_STRING:
1004 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1005 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1006 break;
1007 case CERT_RDN_PRINTABLE_STRING:
1008 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1009 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1010 break;
1011 case CERT_RDN_TELETEX_STRING:
1012 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1013 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1014 break;
1015 case CERT_RDN_VIDEOTEX_STRING:
1016 ret = CRYPT_AsnEncodeStringCoerce(value,
1017 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1018 break;
1019 case CERT_RDN_IA5_STRING:
1020 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1021 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1022 break;
1023 case CERT_RDN_GRAPHIC_STRING:
1024 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1025 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1026 break;
1027 case CERT_RDN_VISIBLE_STRING:
1028 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1029 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1030 break;
1031 case CERT_RDN_GENERAL_STRING:
1032 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1033 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1034 break;
1035 case CERT_RDN_UNIVERSAL_STRING:
1036 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1037 SetLastError(CRYPT_E_ASN1_CHOICE);
1038 ret = FALSE;
1039 break;
1040 case CERT_RDN_BMP_STRING:
1041 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1042 pbEncoded, pcbEncoded);
1043 break;
1044 case CERT_RDN_UTF8_STRING:
1045 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1046 pbEncoded, pcbEncoded);
1047 break;
1048 default:
1049 SetLastError(CRYPT_E_ASN1_CHOICE);
1050 ret = FALSE;
1053 __EXCEPT_PAGE_FAULT
1055 SetLastError(STATUS_ACCESS_VIOLATION);
1056 ret = FALSE;
1058 __ENDTRY
1059 return ret;
1062 static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1063 CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1064 BYTE *pbEncoded, DWORD *pcbEncoded)
1066 DWORD bytesNeeded = 0, lenBytes, size;
1067 BOOL ret;
1069 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1070 0, NULL, NULL, &size);
1071 if (ret)
1073 bytesNeeded += size;
1074 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1075 * with dwValueType, so "cast" it to get its encoded size
1077 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1078 (CERT_NAME_VALUE *)&attr->dwValueType, 0, NULL, NULL, &size);
1079 if (ret)
1081 bytesNeeded += size;
1082 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1083 bytesNeeded += 1 + lenBytes;
1084 if (pbEncoded)
1086 if (*pcbEncoded < bytesNeeded)
1088 SetLastError(ERROR_MORE_DATA);
1089 ret = FALSE;
1091 else
1093 *pbEncoded++ = ASN_SEQUENCE;
1094 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1095 &lenBytes);
1096 pbEncoded += lenBytes;
1097 size = bytesNeeded - 1 - lenBytes;
1098 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1099 attr->pszObjId, 0, NULL, pbEncoded, &size);
1100 if (ret)
1102 pbEncoded += size;
1103 size = bytesNeeded - 1 - lenBytes - size;
1104 ret = nameValueEncodeFunc(dwCertEncodingType,
1105 NULL, (CERT_NAME_VALUE *)&attr->dwValueType,
1106 0, NULL, pbEncoded, &size);
1107 if (!ret)
1108 *pcbEncoded = size;
1112 if (ret)
1113 *pcbEncoded = bytesNeeded;
1115 else
1117 /* Have to propagate index of failing character */
1118 *pcbEncoded = size;
1121 return ret;
1124 static int BLOBComp(const void *l, const void *r)
1126 const CRYPT_DER_BLOB *a = (const CRYPT_DER_BLOB *)l, *b = (const CRYPT_DER_BLOB *)r;
1127 int ret;
1129 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1130 ret = a->cbData - b->cbData;
1131 return ret;
1134 typedef struct _CRYPT_SET_OF {
1135 DWORD cValue;
1136 PCRYPT_DER_BLOB rgValue;
1137 } CRYPT_SET_OF;
1139 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1141 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1142 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1143 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1145 const CRYPT_SET_OF *set = (const CRYPT_SET_OF *)pvStructInfo;
1146 DWORD bytesNeeded = 0, lenBytes, i;
1147 BOOL ret;
1149 for (i = 0; i < set->cValue; i++)
1150 bytesNeeded += set->rgValue[i].cbData;
1151 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1152 bytesNeeded += 1 + lenBytes;
1153 if (!pbEncoded)
1155 *pcbEncoded = bytesNeeded;
1156 ret = TRUE;
1158 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1159 pbEncoded, pcbEncoded, bytesNeeded)))
1161 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1162 pbEncoded = *(BYTE **)pbEncoded;
1163 qsort(set->rgValue, set->cValue, sizeof(CRYPT_DER_BLOB), BLOBComp);
1164 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1165 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1166 pbEncoded += lenBytes;
1167 for (i = 0; ret && i < set->cValue; i++)
1169 memcpy(pbEncoded, set->rgValue[i].pbData, set->rgValue[i].cbData);
1170 pbEncoded += set->rgValue[i].cbData;
1173 return ret;
1176 struct DERSetDescriptor
1178 DWORD cItems;
1179 const void *items;
1180 size_t itemSize;
1181 size_t itemOffset;
1182 CryptEncodeObjectExFunc encode;
1185 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,
1186 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1187 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1189 const struct DERSetDescriptor *desc =
1190 (const struct DERSetDescriptor *)pvStructInfo;
1191 CRYPT_SET_OF setOf = { 0, NULL };
1192 BOOL ret = TRUE;
1193 DWORD i;
1195 if (desc->cItems)
1197 setOf.rgValue = CryptMemAlloc(desc->cItems * sizeof(CRYPT_DER_BLOB));
1198 if (!setOf.rgValue)
1199 ret = FALSE;
1200 else
1202 setOf.cValue = desc->cItems;
1203 memset(setOf.rgValue, 0, setOf.cValue * sizeof(CRYPT_DER_BLOB));
1206 for (i = 0; ret && i < setOf.cValue; i++)
1208 ret = desc->encode(dwCertEncodingType, lpszStructType,
1209 (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
1210 0, NULL, NULL, &setOf.rgValue[i].cbData);
1211 if (ret)
1213 setOf.rgValue[i].pbData = CryptMemAlloc(setOf.rgValue[i].cbData);
1214 if (!setOf.rgValue[i].pbData)
1215 ret = FALSE;
1216 else
1217 ret = desc->encode(dwCertEncodingType, lpszStructType,
1218 (const BYTE *)desc->items + i * desc->itemSize +
1219 desc->itemOffset, 0, NULL, setOf.rgValue[i].pbData,
1220 &setOf.rgValue[i].cbData);
1222 /* Some functions propagate their errors through the size */
1223 if (!ret)
1224 *pcbEncoded = setOf.rgValue[i].cbData;
1226 if (ret)
1228 DWORD bytesNeeded = 0, lenBytes;
1229 BOOL ret;
1231 for (i = 0; i < setOf.cValue; i++)
1232 bytesNeeded += setOf.rgValue[i].cbData;
1233 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1234 bytesNeeded += 1 + lenBytes;
1235 if (!pbEncoded)
1236 *pcbEncoded = bytesNeeded;
1237 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1238 pbEncoded, pcbEncoded, bytesNeeded)))
1240 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1241 pbEncoded = *(BYTE **)pbEncoded;
1242 qsort(setOf.rgValue, setOf.cValue, sizeof(CRYPT_DER_BLOB),
1243 BLOBComp);
1244 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1245 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1246 pbEncoded += lenBytes;
1247 for (i = 0; i < setOf.cValue; i++)
1249 memcpy(pbEncoded, setOf.rgValue[i].pbData,
1250 setOf.rgValue[i].cbData);
1251 pbEncoded += setOf.rgValue[i].cbData;
1255 for (i = 0; i < setOf.cValue; i++)
1256 CryptMemFree(setOf.rgValue[i].pbData);
1257 CryptMemFree(setOf.rgValue);
1258 return ret;
1261 static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
1262 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1263 DWORD *pcbEncoded)
1265 BOOL ret;
1266 CRYPT_SET_OF setOf = { 0, NULL };
1268 __TRY
1270 DWORD i;
1272 ret = TRUE;
1273 if (rdn->cRDNAttr)
1275 setOf.cValue = rdn->cRDNAttr;
1276 setOf.rgValue = CryptMemAlloc(rdn->cRDNAttr *
1277 sizeof(CRYPT_DER_BLOB));
1278 if (!setOf.rgValue)
1279 ret = FALSE;
1280 else
1281 memset(setOf.rgValue, 0, setOf.cValue * sizeof(CRYPT_DER_BLOB));
1283 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1285 setOf.rgValue[i].cbData = 0;
1286 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1287 nameValueEncodeFunc, NULL, &setOf.rgValue[i].cbData);
1288 if (ret)
1290 setOf.rgValue[i].pbData =
1291 CryptMemAlloc(setOf.rgValue[i].cbData);
1292 if (!setOf.rgValue[i].pbData)
1293 ret = FALSE;
1294 else
1295 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1296 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1297 setOf.rgValue[i].pbData, &setOf.rgValue[i].cbData);
1299 if (!ret)
1301 /* Have to propagate index of failing character */
1302 *pcbEncoded = setOf.rgValue[i].cbData;
1305 if (ret)
1306 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1307 pbEncoded, pcbEncoded);
1308 for (i = 0; i < setOf.cValue; i++)
1309 CryptMemFree(setOf.rgValue[i].pbData);
1311 __EXCEPT_PAGE_FAULT
1313 SetLastError(STATUS_ACCESS_VIOLATION);
1314 ret = FALSE;
1316 __ENDTRY
1317 CryptMemFree(setOf.rgValue);
1318 return ret;
1321 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1322 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1323 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1325 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1326 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1327 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1328 DWORD *pcbEncoded)
1330 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1331 BOOL ret;
1333 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1334 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1335 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1336 else
1337 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1338 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1339 return ret;
1342 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1343 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1344 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1346 BOOL ret = TRUE;
1348 __TRY
1350 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1351 DWORD bytesNeeded = 0, lenBytes, size, i;
1353 TRACE("encoding name with %d RDNs\n", info->cRDN);
1354 ret = TRUE;
1355 for (i = 0; ret && i < info->cRDN; i++)
1357 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1358 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1359 if (ret)
1360 bytesNeeded += size;
1361 else
1362 *pcbEncoded = size;
1364 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1365 bytesNeeded += 1 + lenBytes;
1366 if (ret)
1368 if (!pbEncoded)
1369 *pcbEncoded = bytesNeeded;
1370 else
1372 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1373 pbEncoded, pcbEncoded, bytesNeeded)))
1375 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1376 pbEncoded = *(BYTE **)pbEncoded;
1377 *pbEncoded++ = ASN_SEQUENCEOF;
1378 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1379 &lenBytes);
1380 pbEncoded += lenBytes;
1381 for (i = 0; ret && i < info->cRDN; i++)
1383 size = bytesNeeded;
1384 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1385 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1386 pbEncoded, &size);
1387 if (ret)
1389 pbEncoded += size;
1390 bytesNeeded -= size;
1392 else
1393 *pcbEncoded = size;
1399 __EXCEPT_PAGE_FAULT
1401 SetLastError(STATUS_ACCESS_VIOLATION);
1402 ret = FALSE;
1404 __ENDTRY
1405 return ret;
1408 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1409 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1410 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1412 BOOL ret = FALSE;
1414 __TRY
1416 const CRYPT_ATTRIBUTE *attr = (const CRYPT_ATTRIBUTE *)pvStructInfo;
1418 if (!attr->pszObjId)
1419 SetLastError(E_INVALIDARG);
1420 else
1422 struct AsnEncodeSequenceItem items[2] = {
1423 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1424 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1427 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1428 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1429 pcbEncoded);
1432 __EXCEPT_PAGE_FAULT
1434 SetLastError(STATUS_ACCESS_VIOLATION);
1436 __ENDTRY
1437 return ret;
1440 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1441 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1442 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1444 BOOL ret = FALSE;
1446 __TRY
1448 const CRYPT_ATTRIBUTES *attributes =
1449 (const CRYPT_ATTRIBUTES *)pvStructInfo;
1450 struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
1451 sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
1453 ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
1454 &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1456 __EXCEPT_PAGE_FAULT
1458 SetLastError(STATUS_ACCESS_VIOLATION);
1460 __ENDTRY
1461 return ret;
1464 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1465 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
1466 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1467 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1468 DWORD *pcbEncoded)
1470 const CRYPT_CONTENT_INFO *info = (const CRYPT_CONTENT_INFO *)pvStructInfo;
1471 struct AsnEncodeSequenceItem items[2] = {
1472 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1473 { NULL, NULL, 0 },
1475 struct AsnConstructedItem constructed = { 0 };
1476 DWORD cItem = 1;
1478 if (info->Content.cbData)
1480 constructed.tag = 0;
1481 constructed.pvStructInfo = &info->Content;
1482 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1483 items[cItem].pvStructInfo = &constructed;
1484 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1485 cItem++;
1487 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1488 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1491 BOOL CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA *digestedData,
1492 void *pvData, DWORD *pcbData)
1494 struct AsnEncodeSequenceItem items[] = {
1495 { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1496 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
1497 0 },
1498 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1499 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1502 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1503 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
1506 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1507 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1508 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1510 BOOL ret = FALSE;
1512 __TRY
1514 const CRYPT_CONTENT_INFO *info =
1515 (const CRYPT_CONTENT_INFO *)pvStructInfo;
1517 if (!info->pszObjId)
1518 SetLastError(E_INVALIDARG);
1519 else
1520 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
1521 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1522 pcbEncoded);
1524 __EXCEPT_PAGE_FAULT
1526 SetLastError(STATUS_ACCESS_VIOLATION);
1528 __ENDTRY
1529 return ret;
1532 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1533 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1534 DWORD *pcbEncoded)
1536 BOOL ret = TRUE;
1537 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1538 DWORD bytesNeeded, lenBytes, encodedLen;
1540 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1541 lstrlenW(str);
1542 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1543 bytesNeeded = 1 + lenBytes + encodedLen;
1544 if (!pbEncoded)
1545 *pcbEncoded = bytesNeeded;
1546 else
1548 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1549 pbEncoded, pcbEncoded, bytesNeeded)))
1551 DWORD i;
1553 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1554 pbEncoded = *(BYTE **)pbEncoded;
1555 *pbEncoded++ = tag;
1556 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1557 pbEncoded += lenBytes;
1558 for (i = 0; i < encodedLen; i++)
1559 *pbEncoded++ = (BYTE)str[i];
1562 return ret;
1565 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
1566 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1567 DWORD *pcbEncoded)
1569 BOOL ret = TRUE;
1570 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1571 DWORD bytesNeeded, lenBytes, encodedLen;
1573 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1574 lstrlenW(str);
1575 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1576 bytesNeeded = 1 + lenBytes + encodedLen;
1577 if (!pbEncoded)
1578 *pcbEncoded = bytesNeeded;
1579 else
1581 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1582 pbEncoded, pcbEncoded, bytesNeeded)))
1584 DWORD i;
1586 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1587 pbEncoded = *(BYTE **)pbEncoded;
1588 *pbEncoded++ = ASN_NUMERICSTRING;
1589 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1590 pbEncoded += lenBytes;
1591 for (i = 0; ret && i < encodedLen; i++)
1593 if (isdigitW(str[i]))
1594 *pbEncoded++ = (BYTE)str[i];
1595 else
1597 *pcbEncoded = i;
1598 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
1599 ret = FALSE;
1604 return ret;
1607 static inline int isprintableW(WCHAR wc)
1609 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
1610 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
1611 wc == '/' || wc == ':' || wc == '=' || wc == '?';
1614 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
1615 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1616 DWORD *pcbEncoded)
1618 BOOL ret = TRUE;
1619 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1620 DWORD bytesNeeded, lenBytes, encodedLen;
1622 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1623 lstrlenW(str);
1624 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1625 bytesNeeded = 1 + lenBytes + encodedLen;
1626 if (!pbEncoded)
1627 *pcbEncoded = bytesNeeded;
1628 else
1630 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1631 pbEncoded, pcbEncoded, bytesNeeded)))
1633 DWORD i;
1635 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1636 pbEncoded = *(BYTE **)pbEncoded;
1637 *pbEncoded++ = ASN_PRINTABLESTRING;
1638 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1639 pbEncoded += lenBytes;
1640 for (i = 0; ret && i < encodedLen; i++)
1642 if (isprintableW(str[i]))
1643 *pbEncoded++ = (BYTE)str[i];
1644 else
1646 *pcbEncoded = i;
1647 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
1648 ret = FALSE;
1653 return ret;
1656 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
1657 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1658 DWORD *pcbEncoded)
1660 BOOL ret = TRUE;
1661 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1662 DWORD bytesNeeded, lenBytes, encodedLen;
1664 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1665 lstrlenW(str);
1666 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1667 bytesNeeded = 1 + lenBytes + encodedLen;
1668 if (!pbEncoded)
1669 *pcbEncoded = bytesNeeded;
1670 else
1672 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1673 pbEncoded, pcbEncoded, bytesNeeded)))
1675 DWORD i;
1677 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1678 pbEncoded = *(BYTE **)pbEncoded;
1679 *pbEncoded++ = ASN_IA5STRING;
1680 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1681 pbEncoded += lenBytes;
1682 for (i = 0; ret && i < encodedLen; i++)
1684 if (str[i] <= 0x7f)
1685 *pbEncoded++ = (BYTE)str[i];
1686 else
1688 *pcbEncoded = i;
1689 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1690 ret = FALSE;
1695 return ret;
1698 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
1699 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1700 DWORD *pcbEncoded)
1702 BOOL ret = TRUE;
1703 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1704 DWORD bytesNeeded, lenBytes, strLen;
1706 /* FIXME: doesn't handle composite characters */
1707 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1708 lstrlenW(str);
1709 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
1710 bytesNeeded = 1 + lenBytes + strLen * 4;
1711 if (!pbEncoded)
1712 *pcbEncoded = bytesNeeded;
1713 else
1715 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1716 pbEncoded, pcbEncoded, bytesNeeded)))
1718 DWORD i;
1720 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1721 pbEncoded = *(BYTE **)pbEncoded;
1722 *pbEncoded++ = ASN_UNIVERSALSTRING;
1723 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
1724 pbEncoded += lenBytes;
1725 for (i = 0; i < strLen; i++)
1727 *pbEncoded++ = 0;
1728 *pbEncoded++ = 0;
1729 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
1730 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
1734 return ret;
1737 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1738 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1739 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1741 BOOL ret = FALSE;
1743 __TRY
1745 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1747 switch (value->dwValueType)
1749 case CERT_RDN_ANY_TYPE:
1750 case CERT_RDN_ENCODED_BLOB:
1751 case CERT_RDN_OCTET_STRING:
1752 SetLastError(CRYPT_E_NOT_CHAR_STRING);
1753 break;
1754 case CERT_RDN_NUMERIC_STRING:
1755 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
1756 pbEncoded, pcbEncoded);
1757 break;
1758 case CERT_RDN_PRINTABLE_STRING:
1759 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
1760 pbEncoded, pcbEncoded);
1761 break;
1762 case CERT_RDN_TELETEX_STRING:
1763 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
1764 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1765 break;
1766 case CERT_RDN_VIDEOTEX_STRING:
1767 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
1768 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1769 break;
1770 case CERT_RDN_IA5_STRING:
1771 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
1772 pbEncoded, pcbEncoded);
1773 break;
1774 case CERT_RDN_GRAPHIC_STRING:
1775 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
1776 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1777 break;
1778 case CERT_RDN_VISIBLE_STRING:
1779 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
1780 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1781 break;
1782 case CERT_RDN_GENERAL_STRING:
1783 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
1784 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1785 break;
1786 case CERT_RDN_UNIVERSAL_STRING:
1787 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
1788 pbEncoded, pcbEncoded);
1789 break;
1790 case CERT_RDN_BMP_STRING:
1791 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1792 pbEncoded, pcbEncoded);
1793 break;
1794 case CERT_RDN_UTF8_STRING:
1795 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1796 pbEncoded, pcbEncoded);
1797 break;
1798 default:
1799 SetLastError(CRYPT_E_ASN1_CHOICE);
1802 __EXCEPT_PAGE_FAULT
1804 SetLastError(STATUS_ACCESS_VIOLATION);
1806 __ENDTRY
1807 return ret;
1810 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
1811 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1812 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1814 BOOL ret;
1816 __TRY
1818 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1819 DWORD bytesNeeded = 0, lenBytes, size, i;
1821 TRACE("encoding name with %d RDNs\n", info->cRDN);
1822 ret = TRUE;
1823 for (i = 0; ret && i < info->cRDN; i++)
1825 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1826 CRYPT_AsnEncodeNameValue, NULL, &size);
1827 if (ret)
1828 bytesNeeded += size;
1830 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1831 bytesNeeded += 1 + lenBytes;
1832 if (ret)
1834 if (!pbEncoded)
1835 *pcbEncoded = bytesNeeded;
1836 else
1838 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1839 pbEncoded, pcbEncoded, bytesNeeded)))
1841 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1842 pbEncoded = *(BYTE **)pbEncoded;
1843 *pbEncoded++ = ASN_SEQUENCEOF;
1844 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1845 &lenBytes);
1846 pbEncoded += lenBytes;
1847 for (i = 0; ret && i < info->cRDN; i++)
1849 size = bytesNeeded;
1850 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1851 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, pbEncoded,
1852 &size);
1853 if (ret)
1855 pbEncoded += size;
1856 bytesNeeded -= size;
1863 __EXCEPT_PAGE_FAULT
1865 SetLastError(STATUS_ACCESS_VIOLATION);
1866 ret = FALSE;
1868 __ENDTRY
1869 return ret;
1872 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1873 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1874 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1876 BOOL val = *(const BOOL *)pvStructInfo, ret;
1878 TRACE("%d\n", val);
1880 if (!pbEncoded)
1882 *pcbEncoded = 3;
1883 ret = TRUE;
1885 else if (*pcbEncoded < 3)
1887 *pcbEncoded = 3;
1888 SetLastError(ERROR_MORE_DATA);
1889 ret = FALSE;
1891 else
1893 *pcbEncoded = 3;
1894 *pbEncoded++ = ASN_BOOL;
1895 *pbEncoded++ = 1;
1896 *pbEncoded++ = val ? 0xff : 0;
1897 ret = TRUE;
1899 TRACE("returning %d (%08x)\n", ret, GetLastError());
1900 return ret;
1903 static BOOL CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY *entry,
1904 BYTE *pbEncoded, DWORD *pcbEncoded)
1906 BOOL ret;
1907 DWORD dataLen;
1908 BYTE tag;
1910 ret = TRUE;
1911 switch (entry->dwAltNameChoice)
1913 case CERT_ALT_NAME_RFC822_NAME:
1914 case CERT_ALT_NAME_DNS_NAME:
1915 case CERT_ALT_NAME_URL:
1916 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1917 if (entry->u.pwszURL)
1919 DWORD i;
1921 /* Not + 1: don't encode the NULL-terminator */
1922 dataLen = lstrlenW(entry->u.pwszURL);
1923 for (i = 0; ret && i < dataLen; i++)
1925 if (entry->u.pwszURL[i] > 0x7f)
1927 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1928 ret = FALSE;
1929 *pcbEncoded = i;
1933 else
1934 dataLen = 0;
1935 break;
1936 case CERT_ALT_NAME_DIRECTORY_NAME:
1937 tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1);
1938 dataLen = entry->u.DirectoryName.cbData;
1939 break;
1940 case CERT_ALT_NAME_IP_ADDRESS:
1941 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1942 dataLen = entry->u.IPAddress.cbData;
1943 break;
1944 case CERT_ALT_NAME_REGISTERED_ID:
1946 struct AsnEncodeTagSwappedItem swapped =
1947 { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID,
1948 CRYPT_AsnEncodeOid };
1950 return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded,
1951 pcbEncoded);
1953 case CERT_ALT_NAME_OTHER_NAME:
1954 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
1955 return FALSE;
1956 default:
1957 SetLastError(E_INVALIDARG);
1958 return FALSE;
1960 if (ret)
1962 DWORD bytesNeeded, lenBytes;
1964 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1965 bytesNeeded = 1 + dataLen + lenBytes;
1966 if (!pbEncoded)
1967 *pcbEncoded = bytesNeeded;
1968 else if (*pcbEncoded < bytesNeeded)
1970 SetLastError(ERROR_MORE_DATA);
1971 *pcbEncoded = bytesNeeded;
1972 ret = FALSE;
1974 else
1976 *pbEncoded++ = tag;
1977 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1978 pbEncoded += lenBytes;
1979 switch (entry->dwAltNameChoice)
1981 case CERT_ALT_NAME_RFC822_NAME:
1982 case CERT_ALT_NAME_DNS_NAME:
1983 case CERT_ALT_NAME_URL:
1985 DWORD i;
1987 for (i = 0; i < dataLen; i++)
1988 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
1989 break;
1991 case CERT_ALT_NAME_DIRECTORY_NAME:
1992 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen);
1993 break;
1994 case CERT_ALT_NAME_IP_ADDRESS:
1995 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
1996 break;
1998 if (ret)
1999 *pcbEncoded = bytesNeeded;
2002 TRACE("returning %d (%08x)\n", ret, GetLastError());
2003 return ret;
2006 static BOOL WINAPI CRYPT_AsnEncodeIntegerSwapBytes(DWORD dwCertEncodingType,
2007 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2008 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2010 BOOL ret;
2012 __TRY
2014 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2015 CRYPT_DATA_BLOB newBlob = { blob->cbData, NULL };
2017 ret = TRUE;
2018 if (newBlob.cbData)
2020 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2021 if (newBlob.pbData)
2023 DWORD i;
2025 for (i = 0; i < newBlob.cbData; i++)
2026 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2028 else
2029 ret = FALSE;
2031 if (ret)
2032 ret = CRYPT_AsnEncodeInteger(dwCertEncodingType, lpszStructType,
2033 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2034 CryptMemFree(newBlob.pbData);
2036 __EXCEPT_PAGE_FAULT
2038 SetLastError(STATUS_ACCESS_VIOLATION);
2039 ret = FALSE;
2041 __ENDTRY
2042 return ret;
2045 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
2046 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2047 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2049 BOOL ret;
2051 __TRY
2053 const CERT_AUTHORITY_KEY_ID_INFO *info =
2054 (const CERT_AUTHORITY_KEY_ID_INFO *)pvStructInfo;
2055 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2056 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2057 struct AsnConstructedItem constructed = { 0 };
2058 DWORD cItem = 0, cSwapped = 0;
2060 if (info->KeyId.cbData)
2062 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2063 swapped[cSwapped].pvStructInfo = &info->KeyId;
2064 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2065 items[cItem].pvStructInfo = &swapped[cSwapped];
2066 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2067 cSwapped++;
2068 cItem++;
2070 if (info->CertIssuer.cbData)
2072 constructed.tag = 1;
2073 constructed.pvStructInfo = &info->CertIssuer;
2074 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2075 items[cItem].pvStructInfo = &constructed;
2076 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2077 cItem++;
2079 if (info->CertSerialNumber.cbData)
2081 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2082 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2083 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2084 items[cItem].pvStructInfo = &swapped[cSwapped];
2085 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2086 cSwapped++;
2087 cItem++;
2089 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2090 pEncodePara, pbEncoded, pcbEncoded);
2092 __EXCEPT_PAGE_FAULT
2094 SetLastError(STATUS_ACCESS_VIOLATION);
2095 ret = FALSE;
2097 __ENDTRY
2098 return ret;
2101 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2102 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2103 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2105 BOOL ret;
2107 __TRY
2109 const CERT_ALT_NAME_INFO *info =
2110 (const CERT_ALT_NAME_INFO *)pvStructInfo;
2111 DWORD bytesNeeded, dataLen, lenBytes, i;
2113 ret = TRUE;
2114 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2115 * can't encode an erroneous entry index if it's bigger than this.
2117 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2119 DWORD len;
2121 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i], NULL,
2122 &len);
2123 if (ret)
2124 dataLen += len;
2125 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2127 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2128 * the bad character, now set the index of the bad
2129 * entry
2131 *pcbEncoded = (BYTE)i <<
2132 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2135 if (ret)
2137 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2138 bytesNeeded = 1 + lenBytes + dataLen;
2139 if (!pbEncoded)
2141 *pcbEncoded = bytesNeeded;
2142 ret = TRUE;
2144 else
2146 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2147 pbEncoded, pcbEncoded, bytesNeeded)))
2149 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2150 pbEncoded = *(BYTE **)pbEncoded;
2151 *pbEncoded++ = ASN_SEQUENCEOF;
2152 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2153 pbEncoded += lenBytes;
2154 for (i = 0; ret && i < info->cAltEntry; i++)
2156 DWORD len = dataLen;
2158 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i],
2159 pbEncoded, &len);
2160 if (ret)
2162 pbEncoded += len;
2163 dataLen -= len;
2170 __EXCEPT_PAGE_FAULT
2172 SetLastError(STATUS_ACCESS_VIOLATION);
2173 ret = FALSE;
2175 __ENDTRY
2176 return ret;
2179 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2180 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2181 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2183 BOOL ret;
2185 __TRY
2187 const CERT_AUTHORITY_KEY_ID2_INFO *info =
2188 (const CERT_AUTHORITY_KEY_ID2_INFO *)pvStructInfo;
2189 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2190 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2191 DWORD cItem = 0, cSwapped = 0;
2193 if (info->KeyId.cbData)
2195 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2196 swapped[cSwapped].pvStructInfo = &info->KeyId;
2197 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2198 items[cItem].pvStructInfo = &swapped[cSwapped];
2199 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2200 cSwapped++;
2201 cItem++;
2203 if (info->AuthorityCertIssuer.cAltEntry)
2205 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2206 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2207 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2208 items[cItem].pvStructInfo = &swapped[cSwapped];
2209 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2210 cSwapped++;
2211 cItem++;
2213 if (info->AuthorityCertSerialNumber.cbData)
2215 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2216 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2217 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2218 items[cItem].pvStructInfo = &swapped[cSwapped];
2219 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2220 cSwapped++;
2221 cItem++;
2223 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2224 pEncodePara, pbEncoded, pcbEncoded);
2226 __EXCEPT_PAGE_FAULT
2228 SetLastError(STATUS_ACCESS_VIOLATION);
2229 ret = FALSE;
2231 __ENDTRY
2232 return ret;
2235 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2236 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2237 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2239 BOOL ret;
2241 __TRY
2243 const CERT_BASIC_CONSTRAINTS_INFO *info =
2244 (const CERT_BASIC_CONSTRAINTS_INFO *)pvStructInfo;
2245 struct AsnEncodeSequenceItem items[3] = {
2246 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2247 { 0 }
2249 DWORD cItem = 1;
2251 if (info->fPathLenConstraint)
2253 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2254 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2255 cItem++;
2257 if (info->cSubtreesConstraint)
2259 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2260 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2261 cItem++;
2263 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2264 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2266 __EXCEPT_PAGE_FAULT
2268 SetLastError(STATUS_ACCESS_VIOLATION);
2269 ret = FALSE;
2271 __ENDTRY
2272 return ret;
2275 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2276 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2277 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2279 BOOL ret;
2281 __TRY
2283 const CERT_BASIC_CONSTRAINTS2_INFO *info =
2284 (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
2285 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2286 DWORD cItem = 0;
2288 if (info->fCA)
2290 items[cItem].pvStructInfo = &info->fCA;
2291 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2292 cItem++;
2294 if (info->fPathLenConstraint)
2296 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2297 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2298 cItem++;
2300 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2301 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2303 __EXCEPT_PAGE_FAULT
2305 SetLastError(STATUS_ACCESS_VIOLATION);
2306 ret = FALSE;
2308 __ENDTRY
2309 return ret;
2312 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
2313 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2314 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2316 BOOL ret;
2318 __TRY
2320 const BLOBHEADER *hdr =
2321 (const BLOBHEADER *)pvStructInfo;
2323 if (hdr->bType != PUBLICKEYBLOB)
2325 SetLastError(E_INVALIDARG);
2326 ret = FALSE;
2328 else
2330 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
2331 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
2332 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
2333 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
2334 struct AsnEncodeSequenceItem items[] = {
2335 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
2336 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
2339 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2340 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
2341 pcbEncoded);
2344 __EXCEPT_PAGE_FAULT
2346 SetLastError(STATUS_ACCESS_VIOLATION);
2347 ret = FALSE;
2349 __ENDTRY
2350 return ret;
2353 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
2354 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2355 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2357 BOOL ret;
2359 __TRY
2361 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2362 DWORD bytesNeeded, lenBytes;
2364 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
2365 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
2367 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
2368 bytesNeeded = 1 + lenBytes + blob->cbData;
2369 if (!pbEncoded)
2371 *pcbEncoded = bytesNeeded;
2372 ret = TRUE;
2374 else
2376 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2377 pcbEncoded, bytesNeeded)))
2379 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2380 pbEncoded = *(BYTE **)pbEncoded;
2381 *pbEncoded++ = ASN_OCTETSTRING;
2382 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
2383 pbEncoded += lenBytes;
2384 if (blob->cbData)
2385 memcpy(pbEncoded, blob->pbData, blob->cbData);
2389 __EXCEPT_PAGE_FAULT
2391 SetLastError(STATUS_ACCESS_VIOLATION);
2392 ret = FALSE;
2394 __ENDTRY
2395 TRACE("returning %d (%08x)\n", ret, GetLastError());
2396 return ret;
2399 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
2400 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2401 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2403 BOOL ret;
2405 __TRY
2407 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2408 DWORD bytesNeeded, lenBytes, dataBytes;
2409 BYTE unusedBits;
2411 /* yep, MS allows cUnusedBits to be >= 8 */
2412 if (!blob->cUnusedBits)
2414 dataBytes = blob->cbData;
2415 unusedBits = 0;
2417 else if (blob->cbData * 8 > blob->cUnusedBits)
2419 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
2420 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
2421 blob->cUnusedBits;
2423 else
2425 dataBytes = 0;
2426 unusedBits = 0;
2428 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
2429 bytesNeeded = 1 + lenBytes + dataBytes + 1;
2430 if (!pbEncoded)
2432 *pcbEncoded = bytesNeeded;
2433 ret = TRUE;
2435 else
2437 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2438 pcbEncoded, bytesNeeded)))
2440 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2441 pbEncoded = *(BYTE **)pbEncoded;
2442 *pbEncoded++ = ASN_BITSTRING;
2443 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
2444 pbEncoded += lenBytes;
2445 *pbEncoded++ = unusedBits;
2446 if (dataBytes)
2448 BYTE mask = 0xff << unusedBits;
2450 if (dataBytes > 1)
2452 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
2453 pbEncoded += dataBytes - 1;
2455 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
2460 __EXCEPT_PAGE_FAULT
2462 SetLastError(STATUS_ACCESS_VIOLATION);
2463 ret = FALSE;
2465 __ENDTRY
2466 return ret;
2469 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
2470 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2471 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2473 BOOL ret;
2475 __TRY
2477 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2478 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
2480 ret = TRUE;
2481 if (newBlob.cbData)
2483 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2484 if (newBlob.pbData)
2486 DWORD i;
2488 for (i = 0; i < newBlob.cbData; i++)
2489 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2491 else
2492 ret = FALSE;
2494 if (ret)
2495 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
2496 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2497 CryptMemFree(newBlob.pbData);
2499 __EXCEPT_PAGE_FAULT
2501 SetLastError(STATUS_ACCESS_VIOLATION);
2502 ret = FALSE;
2504 __ENDTRY
2505 return ret;
2508 BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
2509 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2510 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2512 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
2514 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
2515 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2518 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
2519 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2520 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2522 BOOL ret;
2524 __TRY
2526 DWORD significantBytes, lenBytes;
2527 BYTE padByte = 0, bytesNeeded;
2528 BOOL pad = FALSE;
2529 const CRYPT_INTEGER_BLOB *blob =
2530 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2532 significantBytes = blob->cbData;
2533 if (significantBytes)
2535 if (blob->pbData[significantBytes - 1] & 0x80)
2537 /* negative, lop off leading (little-endian) 0xffs */
2538 for (; significantBytes > 0 &&
2539 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
2541 if (blob->pbData[significantBytes - 1] < 0x80)
2543 padByte = 0xff;
2544 pad = TRUE;
2547 else
2549 /* positive, lop off leading (little-endian) zeroes */
2550 for (; significantBytes > 0 &&
2551 !blob->pbData[significantBytes - 1]; significantBytes--)
2553 if (significantBytes == 0)
2554 significantBytes = 1;
2555 if (blob->pbData[significantBytes - 1] > 0x7f)
2557 padByte = 0;
2558 pad = TRUE;
2562 if (pad)
2563 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2564 else
2565 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2566 bytesNeeded = 1 + lenBytes + significantBytes;
2567 if (pad)
2568 bytesNeeded++;
2569 if (!pbEncoded)
2571 *pcbEncoded = bytesNeeded;
2572 ret = TRUE;
2574 else
2576 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2577 pcbEncoded, bytesNeeded)))
2579 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2580 pbEncoded = *(BYTE **)pbEncoded;
2581 *pbEncoded++ = ASN_INTEGER;
2582 if (pad)
2584 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2585 pbEncoded += lenBytes;
2586 *pbEncoded++ = padByte;
2588 else
2590 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2591 pbEncoded += lenBytes;
2593 for (; significantBytes > 0; significantBytes--)
2594 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2598 __EXCEPT_PAGE_FAULT
2600 SetLastError(STATUS_ACCESS_VIOLATION);
2601 ret = FALSE;
2603 __ENDTRY
2604 return ret;
2607 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
2608 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2609 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2611 BOOL ret;
2613 __TRY
2615 DWORD significantBytes, lenBytes;
2616 BYTE bytesNeeded;
2617 BOOL pad = FALSE;
2618 const CRYPT_INTEGER_BLOB *blob =
2619 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2621 significantBytes = blob->cbData;
2622 if (significantBytes)
2624 /* positive, lop off leading (little-endian) zeroes */
2625 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
2626 significantBytes--)
2628 if (significantBytes == 0)
2629 significantBytes = 1;
2630 if (blob->pbData[significantBytes - 1] > 0x7f)
2631 pad = TRUE;
2633 if (pad)
2634 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2635 else
2636 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2637 bytesNeeded = 1 + lenBytes + significantBytes;
2638 if (pad)
2639 bytesNeeded++;
2640 if (!pbEncoded)
2642 *pcbEncoded = bytesNeeded;
2643 ret = TRUE;
2645 else
2647 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2648 pcbEncoded, bytesNeeded)))
2650 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2651 pbEncoded = *(BYTE **)pbEncoded;
2652 *pbEncoded++ = ASN_INTEGER;
2653 if (pad)
2655 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2656 pbEncoded += lenBytes;
2657 *pbEncoded++ = 0;
2659 else
2661 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2662 pbEncoded += lenBytes;
2664 for (; significantBytes > 0; significantBytes--)
2665 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2669 __EXCEPT_PAGE_FAULT
2671 SetLastError(STATUS_ACCESS_VIOLATION);
2672 ret = FALSE;
2674 __ENDTRY
2675 return ret;
2678 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
2679 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2680 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2682 CRYPT_INTEGER_BLOB blob;
2683 BOOL ret;
2685 /* Encode as an unsigned integer, then change the tag to enumerated */
2686 blob.cbData = sizeof(DWORD);
2687 blob.pbData = (BYTE *)pvStructInfo;
2688 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
2689 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2690 if (ret && pbEncoded)
2692 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2693 pbEncoded = *(BYTE **)pbEncoded;
2694 pbEncoded[0] = ASN_ENUMERATED;
2696 return ret;
2699 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
2700 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2701 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2703 BOOL ret;
2705 __TRY
2707 SYSTEMTIME sysTime;
2708 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2709 * temporary buffer because the output buffer is not NULL-terminated.
2711 char buf[16];
2712 static const DWORD bytesNeeded = sizeof(buf) - 1;
2714 if (!pbEncoded)
2716 *pcbEncoded = bytesNeeded;
2717 ret = TRUE;
2719 else
2721 /* Sanity check the year, this is a two-digit year format */
2722 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2723 &sysTime);
2724 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
2726 SetLastError(CRYPT_E_BAD_ENCODE);
2727 ret = FALSE;
2729 if (ret)
2731 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2732 pbEncoded, pcbEncoded, bytesNeeded)))
2734 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2735 pbEncoded = *(BYTE **)pbEncoded;
2736 buf[0] = ASN_UTCTIME;
2737 buf[1] = bytesNeeded - 2;
2738 snprintf(buf + 2, sizeof(buf) - 2,
2739 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
2740 sysTime.wYear - 2000 : sysTime.wYear - 1900,
2741 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2742 sysTime.wMinute, sysTime.wSecond);
2743 memcpy(pbEncoded, buf, bytesNeeded);
2748 __EXCEPT_PAGE_FAULT
2750 SetLastError(STATUS_ACCESS_VIOLATION);
2751 ret = FALSE;
2753 __ENDTRY
2754 return ret;
2757 static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
2758 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2759 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2761 BOOL ret;
2763 __TRY
2765 SYSTEMTIME sysTime;
2766 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2767 * temporary buffer because the output buffer is not NULL-terminated.
2769 char buf[18];
2770 static const DWORD bytesNeeded = sizeof(buf) - 1;
2772 if (!pbEncoded)
2774 *pcbEncoded = bytesNeeded;
2775 ret = TRUE;
2777 else
2779 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2780 &sysTime);
2781 if (ret)
2782 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2783 pcbEncoded, bytesNeeded);
2784 if (ret)
2786 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2787 pbEncoded = *(BYTE **)pbEncoded;
2788 buf[0] = ASN_GENERALTIME;
2789 buf[1] = bytesNeeded - 2;
2790 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
2791 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2792 sysTime.wMinute, sysTime.wSecond);
2793 memcpy(pbEncoded, buf, bytesNeeded);
2797 __EXCEPT_PAGE_FAULT
2799 SetLastError(STATUS_ACCESS_VIOLATION);
2800 ret = FALSE;
2802 __ENDTRY
2803 return ret;
2806 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
2807 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2808 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2810 BOOL ret;
2812 __TRY
2814 SYSTEMTIME sysTime;
2816 /* Check the year, if it's in the UTCTime range call that encode func */
2817 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
2818 return FALSE;
2819 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
2820 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
2821 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2822 else
2823 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
2824 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
2825 pcbEncoded);
2827 __EXCEPT_PAGE_FAULT
2829 SetLastError(STATUS_ACCESS_VIOLATION);
2830 ret = FALSE;
2832 __ENDTRY
2833 return ret;
2836 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
2837 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2838 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2840 BOOL ret;
2842 __TRY
2844 DWORD bytesNeeded, dataLen, lenBytes, i;
2845 const CRYPT_SEQUENCE_OF_ANY *seq =
2846 (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2848 for (i = 0, dataLen = 0; i < seq->cValue; i++)
2849 dataLen += seq->rgValue[i].cbData;
2850 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2851 bytesNeeded = 1 + lenBytes + dataLen;
2852 if (!pbEncoded)
2854 *pcbEncoded = bytesNeeded;
2855 ret = TRUE;
2857 else
2859 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2860 pcbEncoded, bytesNeeded)))
2862 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2863 pbEncoded = *(BYTE **)pbEncoded;
2864 *pbEncoded++ = ASN_SEQUENCEOF;
2865 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2866 pbEncoded += lenBytes;
2867 for (i = 0; i < seq->cValue; i++)
2869 memcpy(pbEncoded, seq->rgValue[i].pbData,
2870 seq->rgValue[i].cbData);
2871 pbEncoded += seq->rgValue[i].cbData;
2876 __EXCEPT_PAGE_FAULT
2878 SetLastError(STATUS_ACCESS_VIOLATION);
2879 ret = FALSE;
2881 __ENDTRY
2882 return ret;
2885 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
2886 BYTE *pbEncoded, DWORD *pcbEncoded)
2888 BOOL ret = TRUE;
2889 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2890 struct AsnConstructedItem constructed = { 0 };
2891 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2892 DWORD cItem = 0, cSwapped = 0;
2894 switch (distPoint->DistPointName.dwDistPointNameChoice)
2896 case CRL_DIST_POINT_NO_NAME:
2897 /* do nothing */
2898 break;
2899 case CRL_DIST_POINT_FULL_NAME:
2900 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
2901 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
2902 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2903 constructed.tag = 0;
2904 constructed.pvStructInfo = &swapped[cSwapped];
2905 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
2906 items[cItem].pvStructInfo = &constructed;
2907 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2908 cSwapped++;
2909 cItem++;
2910 break;
2911 case CRL_DIST_POINT_ISSUER_RDN_NAME:
2912 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2913 ret = FALSE;
2914 break;
2915 default:
2916 ret = FALSE;
2918 if (ret && distPoint->ReasonFlags.cbData)
2920 swapped[cSwapped].tag = ASN_CONTEXT | 1;
2921 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
2922 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
2923 items[cItem].pvStructInfo = &swapped[cSwapped];
2924 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2925 cSwapped++;
2926 cItem++;
2928 if (ret && distPoint->CRLIssuer.cAltEntry)
2930 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
2931 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
2932 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2933 items[cItem].pvStructInfo = &swapped[cSwapped];
2934 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2935 cSwapped++;
2936 cItem++;
2938 if (ret)
2939 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
2940 pbEncoded, pcbEncoded);
2941 return ret;
2944 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
2945 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2946 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2948 BOOL ret;
2950 __TRY
2952 const CRL_DIST_POINTS_INFO *info =
2953 (const CRL_DIST_POINTS_INFO *)pvStructInfo;
2955 if (!info->cDistPoint)
2957 SetLastError(E_INVALIDARG);
2958 ret = FALSE;
2960 else
2962 DWORD bytesNeeded, dataLen, lenBytes, i;
2964 ret = TRUE;
2965 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
2967 DWORD len;
2969 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
2970 &len);
2971 if (ret)
2972 dataLen += len;
2973 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2975 /* Have to propagate index of failing character */
2976 *pcbEncoded = len;
2979 if (ret)
2981 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2982 bytesNeeded = 1 + lenBytes + dataLen;
2983 if (!pbEncoded)
2985 *pcbEncoded = bytesNeeded;
2986 ret = TRUE;
2988 else
2990 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2991 pbEncoded, pcbEncoded, bytesNeeded)))
2993 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2994 pbEncoded = *(BYTE **)pbEncoded;
2995 *pbEncoded++ = ASN_SEQUENCEOF;
2996 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2997 pbEncoded += lenBytes;
2998 for (i = 0; ret && i < info->cDistPoint; i++)
3000 DWORD len = dataLen;
3002 ret = CRYPT_AsnEncodeDistPoint(
3003 &info->rgDistPoint[i], pbEncoded, &len);
3004 if (ret)
3006 pbEncoded += len;
3007 dataLen -= len;
3015 __EXCEPT_PAGE_FAULT
3017 SetLastError(STATUS_ACCESS_VIOLATION);
3018 ret = FALSE;
3020 __ENDTRY
3021 return ret;
3024 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3025 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3026 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3028 BOOL ret;
3030 __TRY
3032 const CERT_ENHKEY_USAGE *usage =
3033 (const CERT_ENHKEY_USAGE *)pvStructInfo;
3034 DWORD bytesNeeded = 0, lenBytes, size, i;
3036 ret = TRUE;
3037 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3039 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3040 usage->rgpszUsageIdentifier[i],
3041 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
3042 if (ret)
3043 bytesNeeded += size;
3045 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3046 bytesNeeded += 1 + lenBytes;
3047 if (ret)
3049 if (!pbEncoded)
3050 *pcbEncoded = bytesNeeded;
3051 else
3053 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3054 pbEncoded, pcbEncoded, bytesNeeded)))
3056 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3057 pbEncoded = *(BYTE **)pbEncoded;
3058 *pbEncoded++ = ASN_SEQUENCEOF;
3059 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
3060 &lenBytes);
3061 pbEncoded += lenBytes;
3062 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3064 size = bytesNeeded;
3065 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3066 usage->rgpszUsageIdentifier[i],
3067 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
3068 &size);
3069 if (ret)
3071 pbEncoded += size;
3072 bytesNeeded -= size;
3079 __EXCEPT_PAGE_FAULT
3081 SetLastError(STATUS_ACCESS_VIOLATION);
3082 ret = FALSE;
3084 __ENDTRY
3085 return ret;
3088 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
3089 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3090 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3092 BOOL ret;
3094 __TRY
3096 const CRL_ISSUING_DIST_POINT *point =
3097 (const CRL_ISSUING_DIST_POINT *)pvStructInfo;
3098 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3099 struct AsnConstructedItem constructed = { 0 };
3100 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3101 DWORD cItem = 0, cSwapped = 0;
3103 ret = TRUE;
3104 switch (point->DistPointName.dwDistPointNameChoice)
3106 case CRL_DIST_POINT_NO_NAME:
3107 /* do nothing */
3108 break;
3109 case CRL_DIST_POINT_FULL_NAME:
3110 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3111 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3112 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3113 constructed.tag = 0;
3114 constructed.pvStructInfo = &swapped[cSwapped];
3115 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3116 items[cItem].pvStructInfo = &constructed;
3117 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3118 cSwapped++;
3119 cItem++;
3120 break;
3121 default:
3122 SetLastError(E_INVALIDARG);
3123 ret = FALSE;
3125 if (ret && point->fOnlyContainsUserCerts)
3127 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3128 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3129 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3130 items[cItem].pvStructInfo = &swapped[cSwapped];
3131 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3132 cSwapped++;
3133 cItem++;
3135 if (ret && point->fOnlyContainsCACerts)
3137 swapped[cSwapped].tag = ASN_CONTEXT | 2;
3138 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3139 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3140 items[cItem].pvStructInfo = &swapped[cSwapped];
3141 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3142 cSwapped++;
3143 cItem++;
3145 if (ret && point->OnlySomeReasonFlags.cbData)
3147 swapped[cSwapped].tag = ASN_CONTEXT | 3;
3148 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3149 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3150 items[cItem].pvStructInfo = &swapped[cSwapped];
3151 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3152 cSwapped++;
3153 cItem++;
3155 if (ret && point->fIndirectCRL)
3157 swapped[cSwapped].tag = ASN_CONTEXT | 4;
3158 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
3159 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3160 items[cItem].pvStructInfo = &swapped[cSwapped];
3161 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3162 cSwapped++;
3163 cItem++;
3165 if (ret)
3166 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3167 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3169 __EXCEPT_PAGE_FAULT
3171 SetLastError(STATUS_ACCESS_VIOLATION);
3172 ret = FALSE;
3174 __ENDTRY
3175 return ret;
3178 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
3179 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3180 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3181 DWORD *pcbEncoded)
3183 BOOL ret;
3184 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3185 (const CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3186 struct AsnEncodeSequenceItem items[] = {
3187 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
3188 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
3191 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3192 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3193 pcbEncoded);
3194 return ret;
3197 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
3198 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3199 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3201 BOOL ret = FALSE;
3203 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
3205 SetLastError(E_INVALIDARG);
3206 return FALSE;
3209 __TRY
3211 const CMSG_SIGNER_INFO *info = (const CMSG_SIGNER_INFO *)pvStructInfo;
3213 if (!info->Issuer.cbData)
3214 SetLastError(E_INVALIDARG);
3215 else
3217 struct AsnEncodeSequenceItem items[7] = {
3218 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
3219 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
3220 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
3221 0 },
3223 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3224 DWORD cItem = 3, cSwapped = 0;
3226 if (info->AuthAttrs.cAttr)
3228 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3229 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
3230 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3231 items[cItem].pvStructInfo = &swapped[cSwapped];
3232 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3233 cSwapped++;
3234 cItem++;
3236 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
3237 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
3238 cItem++;
3239 items[cItem].pvStructInfo = &info->EncryptedHash;
3240 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
3241 cItem++;
3242 if (info->UnauthAttrs.cAttr)
3244 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
3245 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
3246 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3247 items[cItem].pvStructInfo = &swapped[cSwapped];
3248 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3249 cSwapped++;
3250 cItem++;
3252 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3253 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3256 __EXCEPT_PAGE_FAULT
3258 SetLastError(STATUS_ACCESS_VIOLATION);
3260 __ENDTRY
3261 return ret;
3264 BOOL CRYPT_AsnEncodePKCSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
3265 DWORD *pcbData)
3267 struct AsnEncodeSequenceItem items[7] = {
3268 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
3270 struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 };
3271 struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 };
3272 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3273 DWORD cItem = 1, cSwapped = 0;
3274 BOOL ret = TRUE;
3276 if (signedInfo->cSignerInfo)
3278 digestAlgorithmsSet.cItems = signedInfo->cSignerInfo;
3279 digestAlgorithmsSet.items = signedInfo->rgSignerInfo;
3280 digestAlgorithmsSet.itemSize = sizeof(CMSG_SIGNER_INFO);
3281 digestAlgorithmsSet.itemOffset =
3282 offsetof(CMSG_SIGNER_INFO, HashAlgorithm);
3283 digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
3284 items[cItem].pvStructInfo = &digestAlgorithmsSet;
3285 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3286 cItem++;
3288 items[cItem].pvStructInfo = &signedInfo->content;
3289 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal;
3290 cItem++;
3291 if (signedInfo->cCertEncoded)
3293 certSet.cItems = signedInfo->cCertEncoded;
3294 certSet.items = signedInfo->rgCertEncoded;
3295 certSet.itemSize = sizeof(CERT_BLOB);
3296 certSet.itemOffset = 0;
3297 certSet.encode = CRYPT_CopyEncodedBlob;
3298 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0;
3299 swapped[cSwapped].pvStructInfo = &certSet;
3300 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3301 items[cItem].pvStructInfo = &swapped[cSwapped];
3302 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3303 cSwapped++;
3304 cItem++;
3306 if (signedInfo->cCrlEncoded)
3308 crlSet.cItems = signedInfo->cCrlEncoded;
3309 crlSet.items = signedInfo->rgCrlEncoded;
3310 crlSet.itemSize = sizeof(CRL_BLOB);
3311 crlSet.itemOffset = 0;
3312 crlSet.encode = CRYPT_CopyEncodedBlob;
3313 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
3314 swapped[cSwapped].pvStructInfo = &crlSet;
3315 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3316 items[cItem].pvStructInfo = &swapped[cSwapped];
3317 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3318 cSwapped++;
3319 cItem++;
3321 if (ret && signedInfo->cSignerInfo)
3323 signerSet.cItems = signedInfo->cSignerInfo;
3324 signerSet.items = signedInfo->rgSignerInfo;
3325 signerSet.itemSize = sizeof(CMSG_SIGNER_INFO);
3326 signerSet.itemOffset = 0;
3327 signerSet.encode = CRYPT_AsnEncodePKCSSignerInfo;
3328 items[cItem].pvStructInfo = &signerSet;
3329 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3330 cItem++;
3332 if (ret)
3333 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
3334 items, cItem, 0, NULL, pvData, pcbData);
3336 return ret;
3339 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
3340 LPCSTR lpszStructType)
3342 CryptEncodeObjectExFunc encodeFunc = NULL;
3344 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3345 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3347 SetLastError(ERROR_FILE_NOT_FOUND);
3348 return NULL;
3351 if (!HIWORD(lpszStructType))
3353 switch (LOWORD(lpszStructType))
3355 case (WORD)X509_CERT:
3356 encodeFunc = CRYPT_AsnEncodeCert;
3357 break;
3358 case (WORD)X509_CERT_TO_BE_SIGNED:
3359 encodeFunc = CRYPT_AsnEncodeCertInfo;
3360 break;
3361 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
3362 encodeFunc = CRYPT_AsnEncodeCRLInfo;
3363 break;
3364 case (WORD)X509_EXTENSIONS:
3365 encodeFunc = CRYPT_AsnEncodeExtensions;
3366 break;
3367 case (WORD)X509_NAME_VALUE:
3368 encodeFunc = CRYPT_AsnEncodeNameValue;
3369 break;
3370 case (WORD)X509_NAME:
3371 encodeFunc = CRYPT_AsnEncodeName;
3372 break;
3373 case (WORD)X509_PUBLIC_KEY_INFO:
3374 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
3375 break;
3376 case (WORD)X509_AUTHORITY_KEY_ID:
3377 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3378 break;
3379 case (WORD)X509_ALTERNATE_NAME:
3380 encodeFunc = CRYPT_AsnEncodeAltName;
3381 break;
3382 case (WORD)X509_BASIC_CONSTRAINTS:
3383 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3384 break;
3385 case (WORD)X509_BASIC_CONSTRAINTS2:
3386 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3387 break;
3388 case (WORD)RSA_CSP_PUBLICKEYBLOB:
3389 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
3390 break;
3391 case (WORD)X509_UNICODE_NAME:
3392 encodeFunc = CRYPT_AsnEncodeUnicodeName;
3393 break;
3394 case (WORD)PKCS_CONTENT_INFO:
3395 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
3396 break;
3397 case (WORD)PKCS_ATTRIBUTE:
3398 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
3399 break;
3400 case (WORD)X509_UNICODE_NAME_VALUE:
3401 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
3402 break;
3403 case (WORD)X509_OCTET_STRING:
3404 encodeFunc = CRYPT_AsnEncodeOctets;
3405 break;
3406 case (WORD)X509_BITS:
3407 case (WORD)X509_KEY_USAGE:
3408 encodeFunc = CRYPT_AsnEncodeBits;
3409 break;
3410 case (WORD)X509_INTEGER:
3411 encodeFunc = CRYPT_AsnEncodeInt;
3412 break;
3413 case (WORD)X509_MULTI_BYTE_INTEGER:
3414 encodeFunc = CRYPT_AsnEncodeInteger;
3415 break;
3416 case (WORD)X509_MULTI_BYTE_UINT:
3417 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
3418 break;
3419 case (WORD)X509_ENUMERATED:
3420 encodeFunc = CRYPT_AsnEncodeEnumerated;
3421 break;
3422 case (WORD)X509_CHOICE_OF_TIME:
3423 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
3424 break;
3425 case (WORD)X509_AUTHORITY_KEY_ID2:
3426 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3427 break;
3428 case (WORD)X509_SEQUENCE_OF_ANY:
3429 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
3430 break;
3431 case (WORD)PKCS_UTC_TIME:
3432 encodeFunc = CRYPT_AsnEncodeUtcTime;
3433 break;
3434 case (WORD)X509_CRL_DIST_POINTS:
3435 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3436 break;
3437 case (WORD)X509_ENHANCED_KEY_USAGE:
3438 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3439 break;
3440 case (WORD)PKCS_ATTRIBUTES:
3441 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3442 break;
3443 case (WORD)X509_ISSUING_DIST_POINT:
3444 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3445 break;
3446 case (WORD)PKCS7_SIGNER_INFO:
3447 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
3448 break;
3451 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3452 encodeFunc = CRYPT_AsnEncodeExtensions;
3453 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3454 encodeFunc = CRYPT_AsnEncodeUtcTime;
3455 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
3456 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3457 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
3458 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3459 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3460 encodeFunc = CRYPT_AsnEncodeEnumerated;
3461 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3462 encodeFunc = CRYPT_AsnEncodeBits;
3463 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3464 encodeFunc = CRYPT_AsnEncodeOctets;
3465 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3466 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3467 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3468 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3469 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3470 encodeFunc = CRYPT_AsnEncodeAltName;
3471 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3472 encodeFunc = CRYPT_AsnEncodeAltName;
3473 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3474 encodeFunc = CRYPT_AsnEncodeAltName;
3475 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3476 encodeFunc = CRYPT_AsnEncodeAltName;
3477 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3478 encodeFunc = CRYPT_AsnEncodeAltName;
3479 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3480 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3481 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3482 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3483 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3484 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3485 return encodeFunc;
3488 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType,
3489 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
3491 static HCRYPTOIDFUNCSET set = NULL;
3492 CryptEncodeObjectFunc encodeFunc = NULL;
3494 if (!set)
3495 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
3496 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3497 (void **)&encodeFunc, hFunc);
3498 return encodeFunc;
3501 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType,
3502 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
3504 static HCRYPTOIDFUNCSET set = NULL;
3505 CryptEncodeObjectExFunc encodeFunc = NULL;
3507 if (!set)
3508 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
3509 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3510 (void **)&encodeFunc, hFunc);
3511 return encodeFunc;
3514 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3515 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
3517 BOOL ret = FALSE;
3518 HCRYPTOIDFUNCADDR hFunc = NULL;
3519 CryptEncodeObjectFunc pCryptEncodeObject = NULL;
3520 CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL;
3522 TRACE_(crypt)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
3523 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
3524 pcbEncoded);
3526 if (!pbEncoded && !pcbEncoded)
3528 SetLastError(ERROR_INVALID_PARAMETER);
3529 return FALSE;
3532 if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType,
3533 lpszStructType)))
3535 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
3536 debugstr_a(lpszStructType));
3537 pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType,
3538 lpszStructType, &hFunc);
3539 if (!pCryptEncodeObject)
3540 pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType,
3541 lpszStructType, &hFunc);
3543 if (pCryptEncodeObject)
3544 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3545 pvStructInfo, pbEncoded, pcbEncoded);
3546 else if (pCryptEncodeObjectEx)
3547 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
3548 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
3549 if (hFunc)
3550 CryptFreeOIDFunctionAddress(hFunc, 0);
3551 TRACE_(crypt)("returning %d\n", ret);
3552 return ret;
3555 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3556 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
3557 void *pvEncoded, DWORD *pcbEncoded)
3559 BOOL ret = FALSE;
3560 HCRYPTOIDFUNCADDR hFunc = NULL;
3561 CryptEncodeObjectExFunc encodeFunc = NULL;
3563 TRACE_(crypt)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
3564 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
3565 pvEncoded, pcbEncoded);
3567 if (!pvEncoded && !pcbEncoded)
3569 SetLastError(ERROR_INVALID_PARAMETER);
3570 return FALSE;
3573 SetLastError(NOERROR);
3574 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
3575 *(BYTE **)pvEncoded = NULL;
3576 encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType);
3577 if (!encodeFunc)
3579 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
3580 debugstr_a(lpszStructType));
3581 encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType,
3582 &hFunc);
3584 if (encodeFunc)
3585 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
3586 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
3587 else
3589 CryptEncodeObjectFunc pCryptEncodeObject =
3590 CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
3592 if (pCryptEncodeObject)
3594 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3596 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3597 pvStructInfo, NULL, pcbEncoded);
3598 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3599 pvEncoded, pcbEncoded, *pcbEncoded)))
3600 ret = pCryptEncodeObject(dwCertEncodingType,
3601 lpszStructType, pvStructInfo, *(BYTE **)pvEncoded,
3602 pcbEncoded);
3604 else
3605 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3606 pvStructInfo, pvEncoded, pcbEncoded);
3609 if (hFunc)
3610 CryptFreeOIDFunctionAddress(hFunc, 0);
3611 TRACE_(crypt)("returning %d\n", ret);
3612 return ret;
3615 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
3616 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3618 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
3619 NULL, 0, NULL, pInfo, pcbInfo);
3622 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
3623 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3624 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3626 BOOL ret;
3627 HCRYPTKEY key;
3628 static CHAR oid[] = szOID_RSA_RSA;
3630 TRACE("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv, dwKeySpec,
3631 dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo,
3632 pInfo, pcbInfo);
3634 if (!pszPublicKeyObjId)
3635 pszPublicKeyObjId = oid;
3636 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
3638 DWORD keySize = 0;
3640 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
3641 if (ret)
3643 LPBYTE pubKey = CryptMemAlloc(keySize);
3645 if (pubKey)
3647 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
3648 &keySize);
3649 if (ret)
3651 DWORD encodedLen = 0;
3653 ret = CryptEncodeObject(dwCertEncodingType,
3654 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
3655 if (ret)
3657 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
3658 strlen(pszPublicKeyObjId) + 1 + encodedLen;
3660 if (!pInfo)
3661 *pcbInfo = sizeNeeded;
3662 else if (*pcbInfo < sizeNeeded)
3664 SetLastError(ERROR_MORE_DATA);
3665 *pcbInfo = sizeNeeded;
3666 ret = FALSE;
3668 else
3670 pInfo->Algorithm.pszObjId = (char *)pInfo +
3671 sizeof(CERT_PUBLIC_KEY_INFO);
3672 lstrcpyA(pInfo->Algorithm.pszObjId,
3673 pszPublicKeyObjId);
3674 pInfo->Algorithm.Parameters.cbData = 0;
3675 pInfo->Algorithm.Parameters.pbData = NULL;
3676 pInfo->PublicKey.pbData =
3677 (BYTE *)pInfo->Algorithm.pszObjId
3678 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
3679 pInfo->PublicKey.cbData = encodedLen;
3680 pInfo->PublicKey.cUnusedBits = 0;
3681 ret = CryptEncodeObject(dwCertEncodingType,
3682 RSA_CSP_PUBLICKEYBLOB, pubKey,
3683 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
3687 CryptMemFree(pubKey);
3689 else
3690 ret = FALSE;
3692 CryptDestroyKey(key);
3694 return ret;
3697 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
3698 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3699 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
3701 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
3702 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
3703 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3705 static HCRYPTOIDFUNCSET set = NULL;
3706 BOOL ret;
3707 ExportPublicKeyInfoExFunc exportFunc = NULL;
3708 HCRYPTOIDFUNCADDR hFunc = NULL;
3710 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv,
3711 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
3712 pvAuxInfo, pInfo, pcbInfo);
3714 if (!hCryptProv)
3716 SetLastError(ERROR_INVALID_PARAMETER);
3717 return FALSE;
3720 if (pszPublicKeyObjId)
3722 if (!set)
3723 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
3725 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
3726 0, (void **)&exportFunc, &hFunc);
3728 if (!exportFunc)
3729 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
3730 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
3731 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
3732 if (hFunc)
3733 CryptFreeOIDFunctionAddress(hFunc, 0);
3734 return ret;
3737 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
3738 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
3740 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
3741 0, 0, NULL, phKey);
3744 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3745 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3746 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3748 BOOL ret;
3749 DWORD pubKeySize = 0;
3751 TRACE("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv,
3752 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3754 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3755 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
3756 if (ret)
3758 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
3760 if (pubKey)
3762 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3763 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
3764 &pubKeySize);
3765 if (ret)
3766 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
3767 phKey);
3768 CryptMemFree(pubKey);
3770 else
3771 ret = FALSE;
3773 return ret;
3776 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
3777 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3778 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
3780 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3781 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3782 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3784 static HCRYPTOIDFUNCSET set = NULL;
3785 BOOL ret;
3786 ImportPublicKeyInfoExFunc importFunc = NULL;
3787 HCRYPTOIDFUNCADDR hFunc = NULL;
3789 TRACE_(crypt)("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv,
3790 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3792 if (!set)
3793 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
3794 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
3795 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
3796 if (!importFunc)
3797 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
3798 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
3799 pvAuxInfo, phKey);
3800 if (hFunc)
3801 CryptFreeOIDFunctionAddress(hFunc, 0);
3802 return ret;