new 818051de2c8769029049ce3d36c6b856f47496c9
[wine/hacks.git] / dlls / crypt32 / encode.c
bloba7cb6617e0170866f6b26e88ab469e1725b639ce
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(crypt);
52 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
53 BYTE *, DWORD *);
55 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
56 * The dwCertEncodingType and lpszStructType are ignored by the built-in
57 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
58 * since it must call functions in external DLLs that follow these signatures.
60 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
61 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
62 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
63 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
64 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
65 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
66 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
67 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
68 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
69 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
70 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
71 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
72 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
73 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
74 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
75 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
76 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
77 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
78 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
79 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
80 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
81 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
82 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
83 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
84 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
85 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
86 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
87 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
88 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
89 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
90 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
91 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
92 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
94 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
95 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
97 static HCRYPTOIDFUNCSET set = NULL;
98 BOOL ret = FALSE;
99 HCRYPTOIDFUNCADDR hFunc;
100 CryptEncodeObjectFunc pCryptEncodeObject;
102 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
103 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
104 pcbEncoded);
106 if (!pbEncoded && !pcbEncoded)
108 SetLastError(ERROR_INVALID_PARAMETER);
109 return FALSE;
112 /* Try registered DLL first.. */
113 if (!set)
114 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
115 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
116 (void **)&pCryptEncodeObject, &hFunc);
117 if (pCryptEncodeObject)
119 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
120 pvStructInfo, pbEncoded, pcbEncoded);
121 CryptFreeOIDFunctionAddress(hFunc, 0);
123 else
125 /* If not, use CryptEncodeObjectEx */
126 ret = CryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
127 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
129 return ret;
132 BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
133 BYTE *pbEncoded, DWORD *pcbEncoded, DWORD bytesNeeded)
135 BOOL ret = TRUE;
137 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
139 if (pEncodePara && pEncodePara->pfnAlloc)
140 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
141 else
142 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
143 if (!*(BYTE **)pbEncoded)
144 ret = FALSE;
145 else
146 *pcbEncoded = bytesNeeded;
148 else if (bytesNeeded > *pcbEncoded)
150 *pcbEncoded = bytesNeeded;
151 SetLastError(ERROR_MORE_DATA);
152 ret = FALSE;
154 else
155 *pcbEncoded = bytesNeeded;
156 return ret;
159 BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
161 DWORD bytesNeeded, significantBytes = 0;
163 if (len <= 0x7f)
164 bytesNeeded = 1;
165 else
167 DWORD temp;
169 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
170 temp <<= 8, significantBytes--)
172 bytesNeeded = significantBytes + 1;
174 if (!pbEncoded)
176 *pcbEncoded = bytesNeeded;
177 return TRUE;
179 if (*pcbEncoded < bytesNeeded)
181 SetLastError(ERROR_MORE_DATA);
182 return FALSE;
184 if (len <= 0x7f)
185 *pbEncoded = (BYTE)len;
186 else
188 DWORD i;
190 *pbEncoded++ = significantBytes | 0x80;
191 for (i = 0; i < significantBytes; i++)
193 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
194 len >>= 8;
197 *pcbEncoded = bytesNeeded;
198 return TRUE;
201 BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
202 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
203 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
205 BOOL ret;
206 DWORD i, dataLen = 0;
208 TRACE("%p, %d, %08x, %p, %p, %d\n", items, cItem, dwFlags, pEncodePara,
209 pbEncoded, *pcbEncoded);
210 for (i = 0, ret = TRUE; ret && i < cItem; i++)
212 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
213 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
214 NULL, &items[i].size);
215 /* Some functions propagate their errors through the size */
216 if (!ret)
217 *pcbEncoded = items[i].size;
218 dataLen += items[i].size;
220 if (ret)
222 DWORD lenBytes, bytesNeeded;
224 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
225 bytesNeeded = 1 + lenBytes + dataLen;
226 if (!pbEncoded)
227 *pcbEncoded = bytesNeeded;
228 else
230 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
231 pcbEncoded, bytesNeeded)))
233 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
234 pbEncoded = *(BYTE **)pbEncoded;
235 *pbEncoded++ = ASN_SEQUENCE;
236 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
237 pbEncoded += lenBytes;
238 for (i = 0; ret && i < cItem; i++)
240 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
241 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
242 NULL, pbEncoded, &items[i].size);
243 /* Some functions propagate their errors through the size */
244 if (!ret)
245 *pcbEncoded = items[i].size;
246 pbEncoded += items[i].size;
251 TRACE("returning %d (%08x)\n", ret, GetLastError());
252 return ret;
255 BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
256 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
257 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
259 BOOL ret;
260 const struct AsnConstructedItem *item =
261 (const struct AsnConstructedItem *)pvStructInfo;
262 DWORD len;
264 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
265 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
267 DWORD dataLen, bytesNeeded;
269 CRYPT_EncodeLen(len, NULL, &dataLen);
270 bytesNeeded = 1 + dataLen + len;
271 if (!pbEncoded)
272 *pcbEncoded = bytesNeeded;
273 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
274 pbEncoded, pcbEncoded, bytesNeeded)))
276 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
277 pbEncoded = *(BYTE **)pbEncoded;
278 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
279 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
280 pbEncoded += dataLen;
281 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
282 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
283 pbEncoded, &len);
284 if (!ret)
286 /* Some functions propagate their errors through the size */
287 *pcbEncoded = len;
291 else
293 /* Some functions propagate their errors through the size */
294 *pcbEncoded = len;
296 return ret;
299 struct AsnEncodeTagSwappedItem
301 BYTE tag;
302 const void *pvStructInfo;
303 CryptEncodeObjectExFunc encodeFunc;
306 /* Sort of a wacky hack, it encodes something using the struct
307 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
308 * given in the struct AsnEncodeTagSwappedItem.
310 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
311 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
312 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
314 BOOL ret;
315 const struct AsnEncodeTagSwappedItem *item =
316 (const struct AsnEncodeTagSwappedItem *)pvStructInfo;
318 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
319 item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
320 if (ret && pbEncoded)
321 *pbEncoded = item->tag;
322 return ret;
325 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
326 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
327 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
329 const DWORD *ver = (const DWORD *)pvStructInfo;
330 BOOL ret;
332 /* CERT_V1 is not encoded */
333 if (*ver == CERT_V1)
335 *pcbEncoded = 0;
336 ret = TRUE;
338 else
340 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
342 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
343 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
345 return ret;
348 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
349 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
350 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
352 const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
353 BOOL ret;
355 if (!pbEncoded)
357 *pcbEncoded = blob->cbData;
358 ret = TRUE;
360 else
362 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
363 pcbEncoded, blob->cbData)))
365 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
366 pbEncoded = *(BYTE **)pbEncoded;
367 if (blob->cbData)
368 memcpy(pbEncoded, blob->pbData, blob->cbData);
369 *pcbEncoded = blob->cbData;
370 ret = TRUE;
373 return ret;
376 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
377 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
378 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
380 BOOL ret;
381 /* This has two filetimes in a row, a NotBefore and a NotAfter */
382 const FILETIME *timePtr = (const FILETIME *)pvStructInfo;
383 struct AsnEncodeSequenceItem items[] = {
384 { timePtr++, CRYPT_AsnEncodeChoiceOfTime, 0 },
385 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
388 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
389 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
390 pcbEncoded);
391 return ret;
394 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
395 * if they are empty.
397 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
398 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
399 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
400 DWORD *pcbEncoded)
402 const CRYPT_ALGORITHM_IDENTIFIER *algo =
403 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
404 static const BYTE asn1Null[] = { ASN_NULL, 0 };
405 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
406 (LPBYTE)asn1Null };
407 BOOL ret;
408 struct AsnEncodeSequenceItem items[2] = {
409 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
410 { NULL, CRYPT_CopyEncodedBlob, 0 },
413 if (algo->Parameters.cbData)
414 items[1].pvStructInfo = &algo->Parameters;
415 else
416 items[1].pvStructInfo = &nullBlob;
417 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
418 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
419 pcbEncoded);
420 return ret;
423 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType,
424 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
425 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
427 const CRYPT_ALGORITHM_IDENTIFIER *algo =
428 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
429 BOOL ret;
430 struct AsnEncodeSequenceItem items[] = {
431 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
432 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
435 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
436 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
437 pcbEncoded);
438 return ret;
441 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
442 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
443 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
445 BOOL ret;
447 __TRY
449 const CERT_PUBLIC_KEY_INFO *info =
450 (const CERT_PUBLIC_KEY_INFO *)pvStructInfo;
451 struct AsnEncodeSequenceItem items[] = {
452 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
453 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
456 TRACE("Encoding public key with OID %s\n",
457 debugstr_a(info->Algorithm.pszObjId));
458 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
459 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
460 pcbEncoded);
462 __EXCEPT_PAGE_FAULT
464 SetLastError(STATUS_ACCESS_VIOLATION);
465 ret = FALSE;
467 __ENDTRY
468 return ret;
471 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
472 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
473 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
475 BOOL ret;
477 __TRY
479 const CERT_SIGNED_CONTENT_INFO *info =
480 (const CERT_SIGNED_CONTENT_INFO *)pvStructInfo;
481 struct AsnEncodeSequenceItem items[] = {
482 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
483 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
484 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
487 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
488 items[2].encodeFunc = CRYPT_AsnEncodeBits;
489 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
490 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
491 pcbEncoded);
493 __EXCEPT_PAGE_FAULT
495 SetLastError(STATUS_ACCESS_VIOLATION);
496 ret = FALSE;
498 __ENDTRY
499 return ret;
502 /* Like in Windows, this blithely ignores the validity of the passed-in
503 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
504 * decode properly, see CRYPT_AsnDecodeCertInfo.
506 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
507 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
508 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
510 BOOL ret;
512 __TRY
514 const CERT_INFO *info = (const CERT_INFO *)pvStructInfo;
515 struct AsnEncodeSequenceItem items[10] = {
516 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
517 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
518 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
519 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
520 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
521 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
522 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfo, 0 },
523 { 0 }
525 struct AsnConstructedItem constructed[3] = { { 0 } };
526 DWORD cItem = 7, cConstructed = 0;
528 if (info->IssuerUniqueId.cbData)
530 constructed[cConstructed].tag = 1;
531 constructed[cConstructed].pvStructInfo = &info->IssuerUniqueId;
532 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
533 items[cItem].pvStructInfo = &constructed[cConstructed];
534 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
535 cConstructed++;
536 cItem++;
538 if (info->SubjectUniqueId.cbData)
540 constructed[cConstructed].tag = 2;
541 constructed[cConstructed].pvStructInfo = &info->SubjectUniqueId;
542 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
543 items[cItem].pvStructInfo = &constructed[cConstructed];
544 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
545 cConstructed++;
546 cItem++;
548 if (info->cExtension)
550 constructed[cConstructed].tag = 3;
551 constructed[cConstructed].pvStructInfo = &info->cExtension;
552 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
553 items[cItem].pvStructInfo = &constructed[cConstructed];
554 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
555 cConstructed++;
556 cItem++;
559 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
560 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
562 __EXCEPT_PAGE_FAULT
564 SetLastError(STATUS_ACCESS_VIOLATION);
565 ret = FALSE;
567 __ENDTRY
568 return ret;
571 static BOOL WINAPI CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
572 BYTE *pbEncoded, DWORD *pcbEncoded)
574 struct AsnEncodeSequenceItem items[3] = {
575 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
576 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
577 { 0 }
579 DWORD cItem = 2;
580 BOOL ret;
582 TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded);
584 if (entry->cExtension)
586 items[cItem].pvStructInfo = &entry->cExtension;
587 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
588 cItem++;
591 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
592 pbEncoded, pcbEncoded);
594 TRACE("returning %d (%08x)\n", ret, GetLastError());
595 return ret;
598 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
599 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
600 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
602 DWORD cCRLEntry = *(const DWORD *)pvStructInfo;
603 DWORD bytesNeeded, dataLen, lenBytes, i;
604 const CRL_ENTRY *rgCRLEntry = *(const CRL_ENTRY *const *)
605 ((const BYTE *)pvStructInfo + sizeof(DWORD));
606 BOOL ret = TRUE;
608 for (i = 0, dataLen = 0; ret && i < cCRLEntry; i++)
610 DWORD size;
612 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
613 if (ret)
614 dataLen += size;
616 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
617 bytesNeeded = 1 + lenBytes + dataLen;
618 if (!pbEncoded)
619 *pcbEncoded = bytesNeeded;
620 else
622 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
623 pcbEncoded, bytesNeeded)))
625 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
626 pbEncoded = *(BYTE **)pbEncoded;
627 *pbEncoded++ = ASN_SEQUENCEOF;
628 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
629 pbEncoded += lenBytes;
630 for (i = 0; i < cCRLEntry; i++)
632 DWORD size = dataLen;
634 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], pbEncoded, &size);
635 pbEncoded += size;
636 dataLen -= size;
640 return ret;
643 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
644 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
645 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
647 const DWORD *ver = (const DWORD *)pvStructInfo;
648 BOOL ret;
650 /* CRL_V1 is not encoded */
651 if (*ver == CRL_V1)
653 *pcbEncoded = 0;
654 ret = TRUE;
656 else
657 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
658 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
659 return ret;
662 /* Like in Windows, this blithely ignores the validity of the passed-in
663 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
664 * decode properly, see CRYPT_AsnDecodeCRLInfo.
666 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
667 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
668 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
670 BOOL ret;
672 __TRY
674 const CRL_INFO *info = (const CRL_INFO *)pvStructInfo;
675 struct AsnEncodeSequenceItem items[7] = {
676 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
677 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
678 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
679 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
680 { 0 }
682 struct AsnConstructedItem constructed[1] = { { 0 } };
683 DWORD cItem = 4, cConstructed = 0;
685 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
687 items[cItem].pvStructInfo = &info->NextUpdate;
688 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
689 cItem++;
691 if (info->cCRLEntry)
693 items[cItem].pvStructInfo = &info->cCRLEntry;
694 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
695 cItem++;
697 if (info->cExtension)
699 constructed[cConstructed].tag = 0;
700 constructed[cConstructed].pvStructInfo = &info->cExtension;
701 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
702 items[cItem].pvStructInfo = &constructed[cConstructed];
703 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
704 cConstructed++;
705 cItem++;
708 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
709 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
711 __EXCEPT_PAGE_FAULT
713 SetLastError(STATUS_ACCESS_VIOLATION);
714 ret = FALSE;
716 __ENDTRY
717 return ret;
720 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
721 DWORD *pcbEncoded)
723 BOOL ret;
724 struct AsnEncodeSequenceItem items[3] = {
725 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
726 { NULL, NULL, 0 },
727 { NULL, NULL, 0 },
729 DWORD cItem = 1;
731 TRACE("%p, %p, %d\n", ext, pbEncoded, *pcbEncoded);
733 if (ext->fCritical)
735 items[cItem].pvStructInfo = &ext->fCritical;
736 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
737 cItem++;
739 items[cItem].pvStructInfo = &ext->Value;
740 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
741 cItem++;
743 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
744 pbEncoded, pcbEncoded);
745 TRACE("returning %d (%08x)\n", ret, GetLastError());
746 return ret;
749 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
750 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
751 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
753 BOOL ret;
755 __TRY
757 DWORD bytesNeeded, dataLen, lenBytes, i;
758 const CERT_EXTENSIONS *exts = (const CERT_EXTENSIONS *)pvStructInfo;
760 ret = TRUE;
761 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
763 DWORD size;
765 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
766 if (ret)
767 dataLen += size;
769 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
770 bytesNeeded = 1 + lenBytes + dataLen;
771 if (!pbEncoded)
772 *pcbEncoded = bytesNeeded;
773 else
775 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
776 pcbEncoded, bytesNeeded)))
778 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
779 pbEncoded = *(BYTE **)pbEncoded;
780 *pbEncoded++ = ASN_SEQUENCEOF;
781 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
782 pbEncoded += lenBytes;
783 for (i = 0; i < exts->cExtension; i++)
785 DWORD size = dataLen;
787 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
788 pbEncoded, &size);
789 pbEncoded += size;
790 dataLen -= size;
795 __EXCEPT_PAGE_FAULT
797 SetLastError(STATUS_ACCESS_VIOLATION);
798 ret = FALSE;
800 __ENDTRY
801 return ret;
804 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
805 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
806 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
808 LPCSTR pszObjId = (LPCSTR)pvStructInfo;
809 DWORD bytesNeeded = 0, lenBytes;
810 BOOL ret = TRUE;
811 int firstPos = 0;
812 BYTE firstByte = 0;
814 TRACE("%s\n", debugstr_a(pszObjId));
816 if (pszObjId)
818 const char *ptr;
819 int val1, val2;
821 if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
823 SetLastError(CRYPT_E_ASN1_ERROR);
824 return FALSE;
826 bytesNeeded++;
827 firstByte = val1 * 40 + val2;
828 ptr = pszObjId + firstPos;
829 while (ret && *ptr)
831 int pos;
833 /* note I assume each component is at most 32-bits long in base 2 */
834 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
836 if (val1 >= 0x10000000)
837 bytesNeeded += 5;
838 else if (val1 >= 0x200000)
839 bytesNeeded += 4;
840 else if (val1 >= 0x4000)
841 bytesNeeded += 3;
842 else if (val1 >= 0x80)
843 bytesNeeded += 2;
844 else
845 bytesNeeded += 1;
846 ptr += pos;
847 if (*ptr == '.')
848 ptr++;
850 else
852 SetLastError(CRYPT_E_ASN1_ERROR);
853 return FALSE;
856 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
858 else
859 lenBytes = 1;
860 bytesNeeded += 1 + lenBytes;
861 if (pbEncoded)
863 if (*pcbEncoded < bytesNeeded)
865 SetLastError(ERROR_MORE_DATA);
866 ret = FALSE;
868 else
870 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
871 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
872 pbEncoded += lenBytes;
873 if (pszObjId)
875 const char *ptr;
876 int val, pos;
878 *pbEncoded++ = firstByte;
879 ptr = pszObjId + firstPos;
880 while (ret && *ptr)
882 sscanf(ptr, "%d%n", &val, &pos);
884 unsigned char outBytes[5];
885 int numBytes, i;
887 if (val >= 0x10000000)
888 numBytes = 5;
889 else if (val >= 0x200000)
890 numBytes = 4;
891 else if (val >= 0x4000)
892 numBytes = 3;
893 else if (val >= 0x80)
894 numBytes = 2;
895 else
896 numBytes = 1;
897 for (i = numBytes; i > 0; i--)
899 outBytes[i - 1] = val & 0x7f;
900 val >>= 7;
902 for (i = 0; i < numBytes - 1; i++)
903 *pbEncoded++ = outBytes[i] | 0x80;
904 *pbEncoded++ = outBytes[i];
905 ptr += pos;
906 if (*ptr == '.')
907 ptr++;
913 *pcbEncoded = bytesNeeded;
914 return ret;
917 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
918 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
919 DWORD *pcbEncoded)
921 BOOL ret = TRUE;
922 LPCSTR str = (LPCSTR)value->Value.pbData;
923 DWORD bytesNeeded, lenBytes, encodedLen;
925 encodedLen = value->Value.cbData ? value->Value.cbData : lstrlenA(str);
926 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
927 bytesNeeded = 1 + lenBytes + encodedLen;
928 if (!pbEncoded)
929 *pcbEncoded = bytesNeeded;
930 else
932 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
933 pbEncoded, pcbEncoded, bytesNeeded)))
935 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
936 pbEncoded = *(BYTE **)pbEncoded;
937 *pbEncoded++ = tag;
938 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
939 pbEncoded += lenBytes;
940 memcpy(pbEncoded, str, encodedLen);
943 return ret;
946 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
947 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
948 DWORD *pcbEncoded)
950 BOOL ret = TRUE;
951 LPCWSTR str = (LPCWSTR)value->Value.pbData;
952 DWORD bytesNeeded, lenBytes, strLen;
954 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
955 lstrlenW(str);
956 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
957 bytesNeeded = 1 + lenBytes + strLen * 2;
958 if (!pbEncoded)
959 *pcbEncoded = bytesNeeded;
960 else
962 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
963 pbEncoded, pcbEncoded, bytesNeeded)))
965 DWORD i;
967 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
968 pbEncoded = *(BYTE **)pbEncoded;
969 *pbEncoded++ = ASN_BMPSTRING;
970 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
971 pbEncoded += lenBytes;
972 for (i = 0; i < strLen; i++)
974 *pbEncoded++ = (str[i] & 0xff00) >> 8;
975 *pbEncoded++ = str[i] & 0x00ff;
979 return ret;
982 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
983 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
984 DWORD *pcbEncoded)
986 BOOL ret = TRUE;
987 LPCWSTR str = (LPCWSTR)value->Value.pbData;
988 DWORD bytesNeeded, lenBytes, encodedLen, strLen;
990 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
991 lstrlenW(str);
992 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
993 NULL);
994 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
995 bytesNeeded = 1 + lenBytes + encodedLen;
996 if (!pbEncoded)
997 *pcbEncoded = bytesNeeded;
998 else
1000 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1001 pbEncoded, pcbEncoded, bytesNeeded)))
1003 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1004 pbEncoded = *(BYTE **)pbEncoded;
1005 *pbEncoded++ = ASN_UTF8STRING;
1006 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1007 pbEncoded += lenBytes;
1008 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
1009 bytesNeeded - lenBytes - 1, NULL, NULL);
1012 return ret;
1015 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
1016 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1017 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1019 BOOL ret = TRUE;
1021 __TRY
1023 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1025 switch (value->dwValueType)
1027 case CERT_RDN_ANY_TYPE:
1028 /* explicitly disallowed */
1029 SetLastError(E_INVALIDARG);
1030 ret = FALSE;
1031 break;
1032 case CERT_RDN_ENCODED_BLOB:
1033 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
1034 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1035 break;
1036 case CERT_RDN_OCTET_STRING:
1037 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1038 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1039 break;
1040 case CERT_RDN_NUMERIC_STRING:
1041 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1042 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1043 break;
1044 case CERT_RDN_PRINTABLE_STRING:
1045 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1046 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1047 break;
1048 case CERT_RDN_TELETEX_STRING:
1049 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1050 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1051 break;
1052 case CERT_RDN_VIDEOTEX_STRING:
1053 ret = CRYPT_AsnEncodeStringCoerce(value,
1054 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1055 break;
1056 case CERT_RDN_IA5_STRING:
1057 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1058 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1059 break;
1060 case CERT_RDN_GRAPHIC_STRING:
1061 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1062 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1063 break;
1064 case CERT_RDN_VISIBLE_STRING:
1065 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1066 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1067 break;
1068 case CERT_RDN_GENERAL_STRING:
1069 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1070 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1071 break;
1072 case CERT_RDN_UNIVERSAL_STRING:
1073 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1074 SetLastError(CRYPT_E_ASN1_CHOICE);
1075 ret = FALSE;
1076 break;
1077 case CERT_RDN_BMP_STRING:
1078 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1079 pbEncoded, pcbEncoded);
1080 break;
1081 case CERT_RDN_UTF8_STRING:
1082 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1083 pbEncoded, pcbEncoded);
1084 break;
1085 default:
1086 SetLastError(CRYPT_E_ASN1_CHOICE);
1087 ret = FALSE;
1090 __EXCEPT_PAGE_FAULT
1092 SetLastError(STATUS_ACCESS_VIOLATION);
1093 ret = FALSE;
1095 __ENDTRY
1096 return ret;
1099 static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1100 CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1101 BYTE *pbEncoded, DWORD *pcbEncoded)
1103 DWORD bytesNeeded = 0, lenBytes, size;
1104 BOOL ret;
1106 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1107 0, NULL, NULL, &size);
1108 if (ret)
1110 bytesNeeded += size;
1111 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1112 * with dwValueType, so "cast" it to get its encoded size
1114 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1115 (CERT_NAME_VALUE *)&attr->dwValueType, 0, NULL, NULL, &size);
1116 if (ret)
1118 bytesNeeded += size;
1119 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1120 bytesNeeded += 1 + lenBytes;
1121 if (pbEncoded)
1123 if (*pcbEncoded < bytesNeeded)
1125 SetLastError(ERROR_MORE_DATA);
1126 ret = FALSE;
1128 else
1130 *pbEncoded++ = ASN_SEQUENCE;
1131 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1132 &lenBytes);
1133 pbEncoded += lenBytes;
1134 size = bytesNeeded - 1 - lenBytes;
1135 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1136 attr->pszObjId, 0, NULL, pbEncoded, &size);
1137 if (ret)
1139 pbEncoded += size;
1140 size = bytesNeeded - 1 - lenBytes - size;
1141 ret = nameValueEncodeFunc(dwCertEncodingType,
1142 NULL, (CERT_NAME_VALUE *)&attr->dwValueType,
1143 0, NULL, pbEncoded, &size);
1144 if (!ret)
1145 *pcbEncoded = size;
1149 if (ret)
1150 *pcbEncoded = bytesNeeded;
1152 else
1154 /* Have to propagate index of failing character */
1155 *pcbEncoded = size;
1158 return ret;
1161 static int BLOBComp(const void *l, const void *r)
1163 const CRYPT_DER_BLOB *a = (const CRYPT_DER_BLOB *)l, *b = (const CRYPT_DER_BLOB *)r;
1164 int ret;
1166 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1167 ret = a->cbData - b->cbData;
1168 return ret;
1171 typedef struct _CRYPT_SET_OF {
1172 DWORD cValue;
1173 PCRYPT_DER_BLOB rgValue;
1174 } CRYPT_SET_OF;
1176 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1178 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1179 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1180 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1182 const CRYPT_SET_OF *set = (const CRYPT_SET_OF *)pvStructInfo;
1183 DWORD bytesNeeded = 0, lenBytes, i;
1184 BOOL ret;
1186 for (i = 0; i < set->cValue; i++)
1187 bytesNeeded += set->rgValue[i].cbData;
1188 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1189 bytesNeeded += 1 + lenBytes;
1190 if (!pbEncoded)
1192 *pcbEncoded = bytesNeeded;
1193 ret = TRUE;
1195 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1196 pbEncoded, pcbEncoded, bytesNeeded)))
1198 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1199 pbEncoded = *(BYTE **)pbEncoded;
1200 qsort(set->rgValue, set->cValue, sizeof(CRYPT_DER_BLOB), BLOBComp);
1201 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1202 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1203 pbEncoded += lenBytes;
1204 for (i = 0; ret && i < set->cValue; i++)
1206 memcpy(pbEncoded, set->rgValue[i].pbData, set->rgValue[i].cbData);
1207 pbEncoded += set->rgValue[i].cbData;
1210 return ret;
1213 static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
1214 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1215 DWORD *pcbEncoded)
1217 BOOL ret;
1218 CRYPT_SET_OF setOf = { 0, NULL };
1220 __TRY
1222 DWORD i;
1224 ret = TRUE;
1225 if (rdn->cRDNAttr)
1227 setOf.cValue = rdn->cRDNAttr;
1228 setOf.rgValue = CryptMemAlloc(rdn->cRDNAttr *
1229 sizeof(CRYPT_DER_BLOB));
1230 if (!setOf.rgValue)
1231 ret = FALSE;
1232 else
1233 memset(setOf.rgValue, 0, setOf.cValue * sizeof(CRYPT_DER_BLOB));
1235 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1237 setOf.rgValue[i].cbData = 0;
1238 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1239 nameValueEncodeFunc, NULL, &setOf.rgValue[i].cbData);
1240 if (ret)
1242 setOf.rgValue[i].pbData =
1243 CryptMemAlloc(setOf.rgValue[i].cbData);
1244 if (!setOf.rgValue[i].pbData)
1245 ret = FALSE;
1246 else
1247 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1248 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1249 setOf.rgValue[i].pbData, &setOf.rgValue[i].cbData);
1251 if (!ret)
1253 /* Have to propagate index of failing character */
1254 *pcbEncoded = setOf.rgValue[i].cbData;
1257 if (ret)
1258 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1259 pbEncoded, pcbEncoded);
1260 for (i = 0; i < setOf.cValue; i++)
1261 CryptMemFree(setOf.rgValue[i].pbData);
1263 __EXCEPT_PAGE_FAULT
1265 SetLastError(STATUS_ACCESS_VIOLATION);
1266 ret = FALSE;
1268 __ENDTRY
1269 CryptMemFree(setOf.rgValue);
1270 return ret;
1273 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1274 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1275 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1277 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1278 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1279 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1280 DWORD *pcbEncoded)
1282 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1283 BOOL ret;
1285 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1286 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1287 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1288 else
1289 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1290 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1291 return ret;
1294 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1295 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1296 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1298 BOOL ret = TRUE;
1300 __TRY
1302 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1303 DWORD bytesNeeded = 0, lenBytes, size, i;
1305 TRACE("encoding name with %d RDNs\n", info->cRDN);
1306 ret = TRUE;
1307 for (i = 0; ret && i < info->cRDN; i++)
1309 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1310 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1311 if (ret)
1312 bytesNeeded += size;
1313 else
1314 *pcbEncoded = size;
1316 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1317 bytesNeeded += 1 + lenBytes;
1318 if (ret)
1320 if (!pbEncoded)
1321 *pcbEncoded = bytesNeeded;
1322 else
1324 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1325 pbEncoded, pcbEncoded, bytesNeeded)))
1327 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1328 pbEncoded = *(BYTE **)pbEncoded;
1329 *pbEncoded++ = ASN_SEQUENCEOF;
1330 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1331 &lenBytes);
1332 pbEncoded += lenBytes;
1333 for (i = 0; ret && i < info->cRDN; i++)
1335 size = bytesNeeded;
1336 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1337 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1338 pbEncoded, &size);
1339 if (ret)
1341 pbEncoded += size;
1342 bytesNeeded -= size;
1344 else
1345 *pcbEncoded = size;
1351 __EXCEPT_PAGE_FAULT
1353 SetLastError(STATUS_ACCESS_VIOLATION);
1354 ret = FALSE;
1356 __ENDTRY
1357 return ret;
1360 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1361 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1362 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1364 BOOL ret = FALSE;
1366 __TRY
1368 const CRYPT_ATTRIBUTE *attr = (const CRYPT_ATTRIBUTE *)pvStructInfo;
1370 if (!attr->pszObjId)
1371 SetLastError(E_INVALIDARG);
1372 else
1374 struct AsnEncodeSequenceItem items[2] = {
1375 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1376 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1379 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1380 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1381 pcbEncoded);
1384 __EXCEPT_PAGE_FAULT
1386 SetLastError(STATUS_ACCESS_VIOLATION);
1388 __ENDTRY
1389 return ret;
1392 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1393 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1394 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1396 BOOL ret = FALSE;
1397 CRYPT_SET_OF setOf = { 0, NULL };
1399 __TRY
1401 DWORD i;
1402 const CRYPT_ATTRIBUTES *attributes =
1403 (const CRYPT_ATTRIBUTES *)pvStructInfo;
1405 ret = TRUE;
1406 if (attributes->cAttr)
1408 setOf.cValue = attributes->cAttr;
1409 setOf.rgValue = CryptMemAlloc(attributes->cAttr *
1410 sizeof(CRYPT_DER_BLOB));
1411 if (!setOf.rgValue)
1412 ret = FALSE;
1413 else
1414 memset(setOf.rgValue, 0, setOf.cValue * sizeof(CRYPT_DER_BLOB));
1416 for (i = 0; ret && i < attributes->cAttr; i++)
1418 ret = CRYPT_AsnEncodePKCSAttribute(dwCertEncodingType, NULL,
1419 &attributes->rgAttr[i], 0, NULL, NULL, &setOf.rgValue[i].cbData);
1420 if (ret)
1422 setOf.rgValue[i].pbData =
1423 CryptMemAlloc(setOf.rgValue[i].cbData);
1424 if (!setOf.rgValue[i].pbData)
1425 ret = FALSE;
1426 else
1428 ret = CRYPT_AsnEncodePKCSAttribute(dwCertEncodingType, NULL,
1429 &attributes->rgAttr[i], 0, NULL, setOf.rgValue[i].pbData,
1430 &setOf.rgValue[i].cbData);
1434 if (ret)
1435 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, dwFlags,
1436 pEncodePara, pbEncoded, pcbEncoded);
1437 for (i = 0; i < setOf.cValue; i++)
1438 CryptMemFree(setOf.rgValue[i].pbData);
1440 __EXCEPT_PAGE_FAULT
1442 SetLastError(STATUS_ACCESS_VIOLATION);
1444 __ENDTRY
1445 CryptMemFree(setOf.rgValue);
1446 return ret;
1449 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1450 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
1451 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1452 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1453 DWORD *pcbEncoded)
1455 const CRYPT_CONTENT_INFO *info = (const CRYPT_CONTENT_INFO *)pvStructInfo;
1456 struct AsnEncodeSequenceItem items[2] = {
1457 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1458 { NULL, NULL, 0 },
1460 struct AsnConstructedItem constructed = { 0 };
1461 DWORD cItem = 1;
1463 if (info->Content.cbData)
1465 constructed.tag = 0;
1466 constructed.pvStructInfo = &info->Content;
1467 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1468 items[cItem].pvStructInfo = &constructed;
1469 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1470 cItem++;
1472 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1473 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1476 BOOL CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA *digestedData,
1477 void *pvData, DWORD *pcbData)
1479 struct AsnEncodeSequenceItem items[] = {
1480 { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1481 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
1482 0 },
1483 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1484 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1487 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1488 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
1491 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1492 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1493 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1495 BOOL ret = FALSE;
1497 __TRY
1499 const CRYPT_CONTENT_INFO *info =
1500 (const CRYPT_CONTENT_INFO *)pvStructInfo;
1502 if (!info->pszObjId)
1503 SetLastError(E_INVALIDARG);
1504 else
1505 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
1506 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1507 pcbEncoded);
1509 __EXCEPT_PAGE_FAULT
1511 SetLastError(STATUS_ACCESS_VIOLATION);
1513 __ENDTRY
1514 return ret;
1517 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1518 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1519 DWORD *pcbEncoded)
1521 BOOL ret = TRUE;
1522 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1523 DWORD bytesNeeded, lenBytes, encodedLen;
1525 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1526 lstrlenW(str);
1527 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1528 bytesNeeded = 1 + lenBytes + encodedLen;
1529 if (!pbEncoded)
1530 *pcbEncoded = bytesNeeded;
1531 else
1533 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1534 pbEncoded, pcbEncoded, bytesNeeded)))
1536 DWORD i;
1538 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1539 pbEncoded = *(BYTE **)pbEncoded;
1540 *pbEncoded++ = tag;
1541 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1542 pbEncoded += lenBytes;
1543 for (i = 0; i < encodedLen; i++)
1544 *pbEncoded++ = (BYTE)str[i];
1547 return ret;
1550 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
1551 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1552 DWORD *pcbEncoded)
1554 BOOL ret = TRUE;
1555 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1556 DWORD bytesNeeded, lenBytes, encodedLen;
1558 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1559 lstrlenW(str);
1560 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1561 bytesNeeded = 1 + lenBytes + encodedLen;
1562 if (!pbEncoded)
1563 *pcbEncoded = bytesNeeded;
1564 else
1566 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1567 pbEncoded, pcbEncoded, bytesNeeded)))
1569 DWORD i;
1571 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1572 pbEncoded = *(BYTE **)pbEncoded;
1573 *pbEncoded++ = ASN_NUMERICSTRING;
1574 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1575 pbEncoded += lenBytes;
1576 for (i = 0; ret && i < encodedLen; i++)
1578 if (isdigitW(str[i]))
1579 *pbEncoded++ = (BYTE)str[i];
1580 else
1582 *pcbEncoded = i;
1583 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
1584 ret = FALSE;
1589 return ret;
1592 static inline int isprintableW(WCHAR wc)
1594 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
1595 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
1596 wc == '/' || wc == ':' || wc == '=' || wc == '?';
1599 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
1600 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1601 DWORD *pcbEncoded)
1603 BOOL ret = TRUE;
1604 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1605 DWORD bytesNeeded, lenBytes, encodedLen;
1607 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1608 lstrlenW(str);
1609 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1610 bytesNeeded = 1 + lenBytes + encodedLen;
1611 if (!pbEncoded)
1612 *pcbEncoded = bytesNeeded;
1613 else
1615 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1616 pbEncoded, pcbEncoded, bytesNeeded)))
1618 DWORD i;
1620 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1621 pbEncoded = *(BYTE **)pbEncoded;
1622 *pbEncoded++ = ASN_PRINTABLESTRING;
1623 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1624 pbEncoded += lenBytes;
1625 for (i = 0; ret && i < encodedLen; i++)
1627 if (isprintableW(str[i]))
1628 *pbEncoded++ = (BYTE)str[i];
1629 else
1631 *pcbEncoded = i;
1632 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
1633 ret = FALSE;
1638 return ret;
1641 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
1642 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1643 DWORD *pcbEncoded)
1645 BOOL ret = TRUE;
1646 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1647 DWORD bytesNeeded, lenBytes, encodedLen;
1649 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1650 lstrlenW(str);
1651 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1652 bytesNeeded = 1 + lenBytes + encodedLen;
1653 if (!pbEncoded)
1654 *pcbEncoded = bytesNeeded;
1655 else
1657 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1658 pbEncoded, pcbEncoded, bytesNeeded)))
1660 DWORD i;
1662 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1663 pbEncoded = *(BYTE **)pbEncoded;
1664 *pbEncoded++ = ASN_IA5STRING;
1665 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1666 pbEncoded += lenBytes;
1667 for (i = 0; ret && i < encodedLen; i++)
1669 if (str[i] <= 0x7f)
1670 *pbEncoded++ = (BYTE)str[i];
1671 else
1673 *pcbEncoded = i;
1674 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1675 ret = FALSE;
1680 return ret;
1683 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
1684 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1685 DWORD *pcbEncoded)
1687 BOOL ret = TRUE;
1688 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1689 DWORD bytesNeeded, lenBytes, strLen;
1691 /* FIXME: doesn't handle composite characters */
1692 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1693 lstrlenW(str);
1694 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
1695 bytesNeeded = 1 + lenBytes + strLen * 4;
1696 if (!pbEncoded)
1697 *pcbEncoded = bytesNeeded;
1698 else
1700 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1701 pbEncoded, pcbEncoded, bytesNeeded)))
1703 DWORD i;
1705 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1706 pbEncoded = *(BYTE **)pbEncoded;
1707 *pbEncoded++ = ASN_UNIVERSALSTRING;
1708 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
1709 pbEncoded += lenBytes;
1710 for (i = 0; i < strLen; i++)
1712 *pbEncoded++ = 0;
1713 *pbEncoded++ = 0;
1714 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
1715 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
1719 return ret;
1722 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1723 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1724 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1726 BOOL ret = FALSE;
1728 __TRY
1730 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1732 switch (value->dwValueType)
1734 case CERT_RDN_ANY_TYPE:
1735 case CERT_RDN_ENCODED_BLOB:
1736 case CERT_RDN_OCTET_STRING:
1737 SetLastError(CRYPT_E_NOT_CHAR_STRING);
1738 break;
1739 case CERT_RDN_NUMERIC_STRING:
1740 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
1741 pbEncoded, pcbEncoded);
1742 break;
1743 case CERT_RDN_PRINTABLE_STRING:
1744 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
1745 pbEncoded, pcbEncoded);
1746 break;
1747 case CERT_RDN_TELETEX_STRING:
1748 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
1749 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1750 break;
1751 case CERT_RDN_VIDEOTEX_STRING:
1752 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
1753 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1754 break;
1755 case CERT_RDN_IA5_STRING:
1756 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
1757 pbEncoded, pcbEncoded);
1758 break;
1759 case CERT_RDN_GRAPHIC_STRING:
1760 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
1761 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1762 break;
1763 case CERT_RDN_VISIBLE_STRING:
1764 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
1765 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1766 break;
1767 case CERT_RDN_GENERAL_STRING:
1768 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
1769 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1770 break;
1771 case CERT_RDN_UNIVERSAL_STRING:
1772 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
1773 pbEncoded, pcbEncoded);
1774 break;
1775 case CERT_RDN_BMP_STRING:
1776 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1777 pbEncoded, pcbEncoded);
1778 break;
1779 case CERT_RDN_UTF8_STRING:
1780 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1781 pbEncoded, pcbEncoded);
1782 break;
1783 default:
1784 SetLastError(CRYPT_E_ASN1_CHOICE);
1787 __EXCEPT_PAGE_FAULT
1789 SetLastError(STATUS_ACCESS_VIOLATION);
1791 __ENDTRY
1792 return ret;
1795 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
1796 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1797 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1799 BOOL ret;
1801 __TRY
1803 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1804 DWORD bytesNeeded = 0, lenBytes, size, i;
1806 TRACE("encoding name with %d RDNs\n", info->cRDN);
1807 ret = TRUE;
1808 for (i = 0; ret && i < info->cRDN; i++)
1810 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1811 CRYPT_AsnEncodeNameValue, NULL, &size);
1812 if (ret)
1813 bytesNeeded += size;
1815 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1816 bytesNeeded += 1 + lenBytes;
1817 if (ret)
1819 if (!pbEncoded)
1820 *pcbEncoded = bytesNeeded;
1821 else
1823 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1824 pbEncoded, pcbEncoded, bytesNeeded)))
1826 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1827 pbEncoded = *(BYTE **)pbEncoded;
1828 *pbEncoded++ = ASN_SEQUENCEOF;
1829 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1830 &lenBytes);
1831 pbEncoded += lenBytes;
1832 for (i = 0; ret && i < info->cRDN; i++)
1834 size = bytesNeeded;
1835 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1836 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, pbEncoded,
1837 &size);
1838 if (ret)
1840 pbEncoded += size;
1841 bytesNeeded -= size;
1848 __EXCEPT_PAGE_FAULT
1850 SetLastError(STATUS_ACCESS_VIOLATION);
1851 ret = FALSE;
1853 __ENDTRY
1854 return ret;
1857 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1858 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1859 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1861 BOOL val = *(const BOOL *)pvStructInfo, ret;
1863 TRACE("%d\n", val);
1865 if (!pbEncoded)
1867 *pcbEncoded = 3;
1868 ret = TRUE;
1870 else if (*pcbEncoded < 3)
1872 *pcbEncoded = 3;
1873 SetLastError(ERROR_MORE_DATA);
1874 ret = FALSE;
1876 else
1878 *pcbEncoded = 3;
1879 *pbEncoded++ = ASN_BOOL;
1880 *pbEncoded++ = 1;
1881 *pbEncoded++ = val ? 0xff : 0;
1882 ret = TRUE;
1884 TRACE("returning %d (%08x)\n", ret, GetLastError());
1885 return ret;
1888 static BOOL CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY *entry,
1889 BYTE *pbEncoded, DWORD *pcbEncoded)
1891 BOOL ret;
1892 DWORD dataLen;
1894 ret = TRUE;
1895 switch (entry->dwAltNameChoice)
1897 case CERT_ALT_NAME_RFC822_NAME:
1898 case CERT_ALT_NAME_DNS_NAME:
1899 case CERT_ALT_NAME_URL:
1900 if (entry->u.pwszURL)
1902 DWORD i;
1904 /* Not + 1: don't encode the NULL-terminator */
1905 dataLen = lstrlenW(entry->u.pwszURL);
1906 for (i = 0; ret && i < dataLen; i++)
1908 if (entry->u.pwszURL[i] > 0x7f)
1910 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1911 ret = FALSE;
1912 *pcbEncoded = i;
1916 else
1917 dataLen = 0;
1918 break;
1919 case CERT_ALT_NAME_IP_ADDRESS:
1920 dataLen = entry->u.IPAddress.cbData;
1921 break;
1922 case CERT_ALT_NAME_REGISTERED_ID:
1923 /* FIXME: encode OID */
1924 case CERT_ALT_NAME_OTHER_NAME:
1925 case CERT_ALT_NAME_DIRECTORY_NAME:
1926 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
1927 return FALSE;
1928 default:
1929 SetLastError(E_INVALIDARG);
1930 return FALSE;
1932 if (ret)
1934 DWORD bytesNeeded, lenBytes;
1936 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1937 bytesNeeded = 1 + dataLen + lenBytes;
1938 if (!pbEncoded)
1939 *pcbEncoded = bytesNeeded;
1940 else if (*pcbEncoded < bytesNeeded)
1942 SetLastError(ERROR_MORE_DATA);
1943 *pcbEncoded = bytesNeeded;
1944 ret = FALSE;
1946 else
1948 *pbEncoded++ = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1949 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1950 pbEncoded += lenBytes;
1951 switch (entry->dwAltNameChoice)
1953 case CERT_ALT_NAME_RFC822_NAME:
1954 case CERT_ALT_NAME_DNS_NAME:
1955 case CERT_ALT_NAME_URL:
1957 DWORD i;
1959 for (i = 0; i < dataLen; i++)
1960 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
1961 break;
1963 case CERT_ALT_NAME_IP_ADDRESS:
1964 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
1965 break;
1967 if (ret)
1968 *pcbEncoded = bytesNeeded;
1971 TRACE("returning %d (%08x)\n", ret, GetLastError());
1972 return ret;
1975 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
1976 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1977 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1979 BOOL ret;
1981 __TRY
1983 const CERT_AUTHORITY_KEY_ID_INFO *info =
1984 (const CERT_AUTHORITY_KEY_ID_INFO *)pvStructInfo;
1985 struct AsnEncodeSequenceItem items[3] = { { 0 } };
1986 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
1987 struct AsnConstructedItem constructed = { 0 };
1988 DWORD cItem = 0, cSwapped = 0;
1990 if (info->KeyId.cbData)
1992 swapped[cSwapped].tag = ASN_CONTEXT | 0;
1993 swapped[cSwapped].pvStructInfo = &info->KeyId;
1994 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
1995 items[cItem].pvStructInfo = &swapped[cSwapped];
1996 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
1997 cSwapped++;
1998 cItem++;
2000 if (info->CertIssuer.cbData)
2002 constructed.tag = 1;
2003 constructed.pvStructInfo = &info->CertIssuer;
2004 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2005 items[cItem].pvStructInfo = &constructed;
2006 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2007 cItem++;
2009 if (info->CertSerialNumber.cbData)
2011 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2012 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2013 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2014 items[cItem].pvStructInfo = &swapped[cSwapped];
2015 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2016 cSwapped++;
2017 cItem++;
2019 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2020 pEncodePara, pbEncoded, pcbEncoded);
2022 __EXCEPT_PAGE_FAULT
2024 SetLastError(STATUS_ACCESS_VIOLATION);
2025 ret = FALSE;
2027 __ENDTRY
2028 return ret;
2031 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2032 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2033 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2035 BOOL ret;
2037 __TRY
2039 const CERT_ALT_NAME_INFO *info =
2040 (const CERT_ALT_NAME_INFO *)pvStructInfo;
2041 DWORD bytesNeeded, dataLen, lenBytes, i;
2043 ret = TRUE;
2044 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2045 * can't encode an erroneous entry index if it's bigger than this.
2047 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2049 DWORD len;
2051 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i], NULL,
2052 &len);
2053 if (ret)
2054 dataLen += len;
2055 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2057 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2058 * the bad character, now set the index of the bad
2059 * entry
2061 *pcbEncoded = (BYTE)i <<
2062 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2065 if (ret)
2067 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2068 bytesNeeded = 1 + lenBytes + dataLen;
2069 if (!pbEncoded)
2071 *pcbEncoded = bytesNeeded;
2072 ret = TRUE;
2074 else
2076 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2077 pbEncoded, pcbEncoded, bytesNeeded)))
2079 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2080 pbEncoded = *(BYTE **)pbEncoded;
2081 *pbEncoded++ = ASN_SEQUENCEOF;
2082 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2083 pbEncoded += lenBytes;
2084 for (i = 0; ret && i < info->cAltEntry; i++)
2086 DWORD len = dataLen;
2088 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i],
2089 pbEncoded, &len);
2090 if (ret)
2092 pbEncoded += len;
2093 dataLen -= len;
2100 __EXCEPT_PAGE_FAULT
2102 SetLastError(STATUS_ACCESS_VIOLATION);
2103 ret = FALSE;
2105 __ENDTRY
2106 return ret;
2109 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2110 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2111 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2113 BOOL ret;
2115 __TRY
2117 const CERT_AUTHORITY_KEY_ID2_INFO *info =
2118 (const CERT_AUTHORITY_KEY_ID2_INFO *)pvStructInfo;
2119 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2120 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2121 DWORD cItem = 0, cSwapped = 0;
2123 if (info->KeyId.cbData)
2125 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2126 swapped[cSwapped].pvStructInfo = &info->KeyId;
2127 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2128 items[cItem].pvStructInfo = &swapped[cSwapped];
2129 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2130 cSwapped++;
2131 cItem++;
2133 if (info->AuthorityCertIssuer.cAltEntry)
2135 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2136 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2137 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2138 items[cItem].pvStructInfo = &swapped[cSwapped];
2139 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2140 cSwapped++;
2141 cItem++;
2143 if (info->AuthorityCertSerialNumber.cbData)
2145 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2146 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2147 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2148 items[cItem].pvStructInfo = &swapped[cSwapped];
2149 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2150 cSwapped++;
2151 cItem++;
2153 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2154 pEncodePara, pbEncoded, pcbEncoded);
2156 __EXCEPT_PAGE_FAULT
2158 SetLastError(STATUS_ACCESS_VIOLATION);
2159 ret = FALSE;
2161 __ENDTRY
2162 return ret;
2165 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2166 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2167 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2169 BOOL ret;
2171 __TRY
2173 const CERT_BASIC_CONSTRAINTS_INFO *info =
2174 (const CERT_BASIC_CONSTRAINTS_INFO *)pvStructInfo;
2175 struct AsnEncodeSequenceItem items[3] = {
2176 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2177 { 0 }
2179 DWORD cItem = 1;
2181 if (info->fPathLenConstraint)
2183 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2184 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2185 cItem++;
2187 if (info->cSubtreesConstraint)
2189 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2190 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2191 cItem++;
2193 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2194 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2196 __EXCEPT_PAGE_FAULT
2198 SetLastError(STATUS_ACCESS_VIOLATION);
2199 ret = FALSE;
2201 __ENDTRY
2202 return ret;
2205 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2206 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2207 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2209 BOOL ret;
2211 __TRY
2213 const CERT_BASIC_CONSTRAINTS2_INFO *info =
2214 (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
2215 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2216 DWORD cItem = 0;
2218 if (info->fCA)
2220 items[cItem].pvStructInfo = &info->fCA;
2221 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2222 cItem++;
2224 if (info->fPathLenConstraint)
2226 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2227 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2228 cItem++;
2230 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2231 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2233 __EXCEPT_PAGE_FAULT
2235 SetLastError(STATUS_ACCESS_VIOLATION);
2236 ret = FALSE;
2238 __ENDTRY
2239 return ret;
2242 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
2243 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2244 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2246 BOOL ret;
2248 __TRY
2250 const BLOBHEADER *hdr =
2251 (const BLOBHEADER *)pvStructInfo;
2253 if (hdr->bType != PUBLICKEYBLOB)
2255 SetLastError(E_INVALIDARG);
2256 ret = FALSE;
2258 else
2260 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
2261 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
2262 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
2263 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
2264 struct AsnEncodeSequenceItem items[] = {
2265 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
2266 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
2269 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2270 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
2271 pcbEncoded);
2274 __EXCEPT_PAGE_FAULT
2276 SetLastError(STATUS_ACCESS_VIOLATION);
2277 ret = FALSE;
2279 __ENDTRY
2280 return ret;
2283 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
2284 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2285 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2287 BOOL ret;
2289 __TRY
2291 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2292 DWORD bytesNeeded, lenBytes;
2294 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
2295 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
2297 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
2298 bytesNeeded = 1 + lenBytes + blob->cbData;
2299 if (!pbEncoded)
2301 *pcbEncoded = bytesNeeded;
2302 ret = TRUE;
2304 else
2306 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2307 pcbEncoded, bytesNeeded)))
2309 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2310 pbEncoded = *(BYTE **)pbEncoded;
2311 *pbEncoded++ = ASN_OCTETSTRING;
2312 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
2313 pbEncoded += lenBytes;
2314 if (blob->cbData)
2315 memcpy(pbEncoded, blob->pbData, blob->cbData);
2319 __EXCEPT_PAGE_FAULT
2321 SetLastError(STATUS_ACCESS_VIOLATION);
2322 ret = FALSE;
2324 __ENDTRY
2325 TRACE("returning %d (%08x)\n", ret, GetLastError());
2326 return ret;
2329 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
2330 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2331 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2333 BOOL ret;
2335 __TRY
2337 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2338 DWORD bytesNeeded, lenBytes, dataBytes;
2339 BYTE unusedBits;
2341 /* yep, MS allows cUnusedBits to be >= 8 */
2342 if (!blob->cUnusedBits)
2344 dataBytes = blob->cbData;
2345 unusedBits = 0;
2347 else if (blob->cbData * 8 > blob->cUnusedBits)
2349 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
2350 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
2351 blob->cUnusedBits;
2353 else
2355 dataBytes = 0;
2356 unusedBits = 0;
2358 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
2359 bytesNeeded = 1 + lenBytes + dataBytes + 1;
2360 if (!pbEncoded)
2362 *pcbEncoded = bytesNeeded;
2363 ret = TRUE;
2365 else
2367 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2368 pcbEncoded, bytesNeeded)))
2370 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2371 pbEncoded = *(BYTE **)pbEncoded;
2372 *pbEncoded++ = ASN_BITSTRING;
2373 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
2374 pbEncoded += lenBytes;
2375 *pbEncoded++ = unusedBits;
2376 if (dataBytes)
2378 BYTE mask = 0xff << unusedBits;
2380 if (dataBytes > 1)
2382 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
2383 pbEncoded += dataBytes - 1;
2385 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
2390 __EXCEPT_PAGE_FAULT
2392 SetLastError(STATUS_ACCESS_VIOLATION);
2393 ret = FALSE;
2395 __ENDTRY
2396 return ret;
2399 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(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 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
2410 ret = TRUE;
2411 if (newBlob.cbData)
2413 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2414 if (newBlob.pbData)
2416 DWORD i;
2418 for (i = 0; i < newBlob.cbData; i++)
2419 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2421 else
2422 ret = FALSE;
2424 if (ret)
2425 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
2426 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2427 CryptMemFree(newBlob.pbData);
2429 __EXCEPT_PAGE_FAULT
2431 SetLastError(STATUS_ACCESS_VIOLATION);
2432 ret = FALSE;
2434 __ENDTRY
2435 return ret;
2438 BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
2439 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2440 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2442 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
2444 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
2445 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2448 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
2449 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2450 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2452 BOOL ret;
2454 __TRY
2456 DWORD significantBytes, lenBytes;
2457 BYTE padByte = 0, bytesNeeded;
2458 BOOL pad = FALSE;
2459 const CRYPT_INTEGER_BLOB *blob =
2460 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2462 significantBytes = blob->cbData;
2463 if (significantBytes)
2465 if (blob->pbData[significantBytes - 1] & 0x80)
2467 /* negative, lop off leading (little-endian) 0xffs */
2468 for (; significantBytes > 0 &&
2469 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
2471 if (blob->pbData[significantBytes - 1] < 0x80)
2473 padByte = 0xff;
2474 pad = TRUE;
2477 else
2479 /* positive, lop off leading (little-endian) zeroes */
2480 for (; significantBytes > 0 &&
2481 !blob->pbData[significantBytes - 1]; significantBytes--)
2483 if (significantBytes == 0)
2484 significantBytes = 1;
2485 if (blob->pbData[significantBytes - 1] > 0x7f)
2487 padByte = 0;
2488 pad = TRUE;
2492 if (pad)
2493 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2494 else
2495 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2496 bytesNeeded = 1 + lenBytes + significantBytes;
2497 if (pad)
2498 bytesNeeded++;
2499 if (!pbEncoded)
2501 *pcbEncoded = bytesNeeded;
2502 ret = TRUE;
2504 else
2506 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2507 pcbEncoded, bytesNeeded)))
2509 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2510 pbEncoded = *(BYTE **)pbEncoded;
2511 *pbEncoded++ = ASN_INTEGER;
2512 if (pad)
2514 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2515 pbEncoded += lenBytes;
2516 *pbEncoded++ = padByte;
2518 else
2520 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2521 pbEncoded += lenBytes;
2523 for (; significantBytes > 0; significantBytes--)
2524 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2528 __EXCEPT_PAGE_FAULT
2530 SetLastError(STATUS_ACCESS_VIOLATION);
2531 ret = FALSE;
2533 __ENDTRY
2534 return ret;
2537 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
2538 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2539 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2541 BOOL ret;
2543 __TRY
2545 DWORD significantBytes, lenBytes;
2546 BYTE bytesNeeded;
2547 BOOL pad = FALSE;
2548 const CRYPT_INTEGER_BLOB *blob =
2549 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2551 significantBytes = blob->cbData;
2552 if (significantBytes)
2554 /* positive, lop off leading (little-endian) zeroes */
2555 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
2556 significantBytes--)
2558 if (significantBytes == 0)
2559 significantBytes = 1;
2560 if (blob->pbData[significantBytes - 1] > 0x7f)
2561 pad = TRUE;
2563 if (pad)
2564 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2565 else
2566 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2567 bytesNeeded = 1 + lenBytes + significantBytes;
2568 if (pad)
2569 bytesNeeded++;
2570 if (!pbEncoded)
2572 *pcbEncoded = bytesNeeded;
2573 ret = TRUE;
2575 else
2577 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2578 pcbEncoded, bytesNeeded)))
2580 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2581 pbEncoded = *(BYTE **)pbEncoded;
2582 *pbEncoded++ = ASN_INTEGER;
2583 if (pad)
2585 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2586 pbEncoded += lenBytes;
2587 *pbEncoded++ = 0;
2589 else
2591 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2592 pbEncoded += lenBytes;
2594 for (; significantBytes > 0; significantBytes--)
2595 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2599 __EXCEPT_PAGE_FAULT
2601 SetLastError(STATUS_ACCESS_VIOLATION);
2602 ret = FALSE;
2604 __ENDTRY
2605 return ret;
2608 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
2609 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2610 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2612 CRYPT_INTEGER_BLOB blob;
2613 BOOL ret;
2615 /* Encode as an unsigned integer, then change the tag to enumerated */
2616 blob.cbData = sizeof(DWORD);
2617 blob.pbData = (BYTE *)pvStructInfo;
2618 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
2619 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2620 if (ret && pbEncoded)
2622 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2623 pbEncoded = *(BYTE **)pbEncoded;
2624 pbEncoded[0] = ASN_ENUMERATED;
2626 return ret;
2629 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
2630 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2631 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2633 BOOL ret;
2635 __TRY
2637 SYSTEMTIME sysTime;
2638 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2639 * temporary buffer because the output buffer is not NULL-terminated.
2641 char buf[16];
2642 static const DWORD bytesNeeded = sizeof(buf) - 1;
2644 if (!pbEncoded)
2646 *pcbEncoded = bytesNeeded;
2647 ret = TRUE;
2649 else
2651 /* Sanity check the year, this is a two-digit year format */
2652 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2653 &sysTime);
2654 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
2656 SetLastError(CRYPT_E_BAD_ENCODE);
2657 ret = FALSE;
2659 if (ret)
2661 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2662 pbEncoded, pcbEncoded, bytesNeeded)))
2664 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2665 pbEncoded = *(BYTE **)pbEncoded;
2666 buf[0] = ASN_UTCTIME;
2667 buf[1] = bytesNeeded - 2;
2668 snprintf(buf + 2, sizeof(buf) - 2,
2669 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
2670 sysTime.wYear - 2000 : sysTime.wYear - 1900,
2671 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2672 sysTime.wMinute, sysTime.wSecond);
2673 memcpy(pbEncoded, buf, bytesNeeded);
2678 __EXCEPT_PAGE_FAULT
2680 SetLastError(STATUS_ACCESS_VIOLATION);
2681 ret = FALSE;
2683 __ENDTRY
2684 return ret;
2687 static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
2688 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2689 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2691 BOOL ret;
2693 __TRY
2695 SYSTEMTIME sysTime;
2696 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2697 * temporary buffer because the output buffer is not NULL-terminated.
2699 char buf[18];
2700 static const DWORD bytesNeeded = sizeof(buf) - 1;
2702 if (!pbEncoded)
2704 *pcbEncoded = bytesNeeded;
2705 ret = TRUE;
2707 else
2709 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2710 &sysTime);
2711 if (ret)
2712 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2713 pcbEncoded, bytesNeeded);
2714 if (ret)
2716 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2717 pbEncoded = *(BYTE **)pbEncoded;
2718 buf[0] = ASN_GENERALTIME;
2719 buf[1] = bytesNeeded - 2;
2720 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
2721 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2722 sysTime.wMinute, sysTime.wSecond);
2723 memcpy(pbEncoded, buf, bytesNeeded);
2727 __EXCEPT_PAGE_FAULT
2729 SetLastError(STATUS_ACCESS_VIOLATION);
2730 ret = FALSE;
2732 __ENDTRY
2733 return ret;
2736 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
2737 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2738 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2740 BOOL ret;
2742 __TRY
2744 SYSTEMTIME sysTime;
2746 /* Check the year, if it's in the UTCTime range call that encode func */
2747 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
2748 return FALSE;
2749 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
2750 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
2751 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2752 else
2753 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
2754 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
2755 pcbEncoded);
2757 __EXCEPT_PAGE_FAULT
2759 SetLastError(STATUS_ACCESS_VIOLATION);
2760 ret = FALSE;
2762 __ENDTRY
2763 return ret;
2766 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
2767 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2768 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2770 BOOL ret;
2772 __TRY
2774 DWORD bytesNeeded, dataLen, lenBytes, i;
2775 const CRYPT_SEQUENCE_OF_ANY *seq =
2776 (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2778 for (i = 0, dataLen = 0; i < seq->cValue; i++)
2779 dataLen += seq->rgValue[i].cbData;
2780 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2781 bytesNeeded = 1 + lenBytes + dataLen;
2782 if (!pbEncoded)
2784 *pcbEncoded = bytesNeeded;
2785 ret = TRUE;
2787 else
2789 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2790 pcbEncoded, bytesNeeded)))
2792 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2793 pbEncoded = *(BYTE **)pbEncoded;
2794 *pbEncoded++ = ASN_SEQUENCEOF;
2795 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2796 pbEncoded += lenBytes;
2797 for (i = 0; i < seq->cValue; i++)
2799 memcpy(pbEncoded, seq->rgValue[i].pbData,
2800 seq->rgValue[i].cbData);
2801 pbEncoded += seq->rgValue[i].cbData;
2806 __EXCEPT_PAGE_FAULT
2808 SetLastError(STATUS_ACCESS_VIOLATION);
2809 ret = FALSE;
2811 __ENDTRY
2812 return ret;
2815 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
2816 BYTE *pbEncoded, DWORD *pcbEncoded)
2818 BOOL ret = TRUE;
2819 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2820 struct AsnConstructedItem constructed = { 0 };
2821 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2822 DWORD cItem = 0, cSwapped = 0;
2824 switch (distPoint->DistPointName.dwDistPointNameChoice)
2826 case CRL_DIST_POINT_NO_NAME:
2827 /* do nothing */
2828 break;
2829 case CRL_DIST_POINT_FULL_NAME:
2830 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
2831 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
2832 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2833 constructed.tag = 0;
2834 constructed.pvStructInfo = &swapped[cSwapped];
2835 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
2836 items[cItem].pvStructInfo = &constructed;
2837 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2838 cSwapped++;
2839 cItem++;
2840 break;
2841 case CRL_DIST_POINT_ISSUER_RDN_NAME:
2842 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2843 ret = FALSE;
2844 break;
2845 default:
2846 ret = FALSE;
2848 if (ret && distPoint->ReasonFlags.cbData)
2850 swapped[cSwapped].tag = ASN_CONTEXT | 1;
2851 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
2852 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
2853 items[cItem].pvStructInfo = &swapped[cSwapped];
2854 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2855 cSwapped++;
2856 cItem++;
2858 if (ret && distPoint->CRLIssuer.cAltEntry)
2860 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
2861 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
2862 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2863 items[cItem].pvStructInfo = &swapped[cSwapped];
2864 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2865 cSwapped++;
2866 cItem++;
2868 if (ret)
2869 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
2870 pbEncoded, pcbEncoded);
2871 return ret;
2874 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
2875 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2876 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2878 BOOL ret;
2880 __TRY
2882 const CRL_DIST_POINTS_INFO *info =
2883 (const CRL_DIST_POINTS_INFO *)pvStructInfo;
2885 if (!info->cDistPoint)
2887 SetLastError(E_INVALIDARG);
2888 ret = FALSE;
2890 else
2892 DWORD bytesNeeded, dataLen, lenBytes, i;
2894 ret = TRUE;
2895 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
2897 DWORD len;
2899 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
2900 &len);
2901 if (ret)
2902 dataLen += len;
2903 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2905 /* Have to propagate index of failing character */
2906 *pcbEncoded = len;
2909 if (ret)
2911 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2912 bytesNeeded = 1 + lenBytes + dataLen;
2913 if (!pbEncoded)
2915 *pcbEncoded = bytesNeeded;
2916 ret = TRUE;
2918 else
2920 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2921 pbEncoded, pcbEncoded, bytesNeeded)))
2923 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2924 pbEncoded = *(BYTE **)pbEncoded;
2925 *pbEncoded++ = ASN_SEQUENCEOF;
2926 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2927 pbEncoded += lenBytes;
2928 for (i = 0; ret && i < info->cDistPoint; i++)
2930 DWORD len = dataLen;
2932 ret = CRYPT_AsnEncodeDistPoint(
2933 &info->rgDistPoint[i], pbEncoded, &len);
2934 if (ret)
2936 pbEncoded += len;
2937 dataLen -= len;
2945 __EXCEPT_PAGE_FAULT
2947 SetLastError(STATUS_ACCESS_VIOLATION);
2948 ret = FALSE;
2950 __ENDTRY
2951 return ret;
2954 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
2955 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2956 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2958 BOOL ret;
2960 __TRY
2962 const CERT_ENHKEY_USAGE *usage =
2963 (const CERT_ENHKEY_USAGE *)pvStructInfo;
2964 DWORD bytesNeeded = 0, lenBytes, size, i;
2966 ret = TRUE;
2967 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
2969 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
2970 usage->rgpszUsageIdentifier[i],
2971 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
2972 if (ret)
2973 bytesNeeded += size;
2975 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2976 bytesNeeded += 1 + lenBytes;
2977 if (ret)
2979 if (!pbEncoded)
2980 *pcbEncoded = bytesNeeded;
2981 else
2983 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2984 pbEncoded, pcbEncoded, bytesNeeded)))
2986 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2987 pbEncoded = *(BYTE **)pbEncoded;
2988 *pbEncoded++ = ASN_SEQUENCEOF;
2989 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
2990 &lenBytes);
2991 pbEncoded += lenBytes;
2992 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
2994 size = bytesNeeded;
2995 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
2996 usage->rgpszUsageIdentifier[i],
2997 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
2998 &size);
2999 if (ret)
3001 pbEncoded += size;
3002 bytesNeeded -= size;
3009 __EXCEPT_PAGE_FAULT
3011 SetLastError(STATUS_ACCESS_VIOLATION);
3012 ret = FALSE;
3014 __ENDTRY
3015 return ret;
3018 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
3019 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3020 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3022 BOOL ret;
3024 __TRY
3026 const CRL_ISSUING_DIST_POINT *point =
3027 (const CRL_ISSUING_DIST_POINT *)pvStructInfo;
3028 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3029 struct AsnConstructedItem constructed = { 0 };
3030 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3031 DWORD cItem = 0, cSwapped = 0;
3033 ret = TRUE;
3034 switch (point->DistPointName.dwDistPointNameChoice)
3036 case CRL_DIST_POINT_NO_NAME:
3037 /* do nothing */
3038 break;
3039 case CRL_DIST_POINT_FULL_NAME:
3040 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3041 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3042 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3043 constructed.tag = 0;
3044 constructed.pvStructInfo = &swapped[cSwapped];
3045 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3046 items[cItem].pvStructInfo = &constructed;
3047 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3048 cSwapped++;
3049 cItem++;
3050 break;
3051 default:
3052 SetLastError(E_INVALIDARG);
3053 ret = FALSE;
3055 if (ret && point->fOnlyContainsUserCerts)
3057 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3058 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3059 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3060 items[cItem].pvStructInfo = &swapped[cSwapped];
3061 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3062 cSwapped++;
3063 cItem++;
3065 if (ret && point->fOnlyContainsCACerts)
3067 swapped[cSwapped].tag = ASN_CONTEXT | 2;
3068 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3069 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3070 items[cItem].pvStructInfo = &swapped[cSwapped];
3071 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3072 cSwapped++;
3073 cItem++;
3075 if (ret && point->OnlySomeReasonFlags.cbData)
3077 swapped[cSwapped].tag = ASN_CONTEXT | 3;
3078 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3079 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3080 items[cItem].pvStructInfo = &swapped[cSwapped];
3081 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3082 cSwapped++;
3083 cItem++;
3085 if (ret && point->fIndirectCRL)
3087 swapped[cSwapped].tag = ASN_CONTEXT | 4;
3088 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
3089 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3090 items[cItem].pvStructInfo = &swapped[cSwapped];
3091 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3092 cSwapped++;
3093 cItem++;
3095 if (ret)
3096 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3097 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3099 __EXCEPT_PAGE_FAULT
3101 SetLastError(STATUS_ACCESS_VIOLATION);
3102 ret = FALSE;
3104 __ENDTRY
3105 return ret;
3108 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
3109 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3110 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3111 DWORD *pcbEncoded)
3113 BOOL ret;
3114 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3115 (const CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3116 struct AsnEncodeSequenceItem items[] = {
3117 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
3118 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
3121 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3122 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3123 pcbEncoded);
3124 return ret;
3127 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
3128 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3129 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3131 BOOL ret = FALSE;
3133 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
3135 SetLastError(E_INVALIDARG);
3136 return FALSE;
3139 __TRY
3141 const CMSG_SIGNER_INFO *info = (const CMSG_SIGNER_INFO *)pvStructInfo;
3143 if (!info->Issuer.cbData)
3144 SetLastError(E_INVALIDARG);
3145 else
3147 struct AsnEncodeSequenceItem items[7] = {
3148 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
3149 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
3150 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
3151 0 },
3152 { &info->HashEncryptionAlgorithm,
3153 CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
3155 DWORD cItem = 4;
3157 if (info->AuthAttrs.cAttr)
3159 items[cItem].pvStructInfo = &info->AuthAttrs;
3160 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3161 cItem++;
3163 if (info->UnauthAttrs.cAttr)
3165 items[cItem].pvStructInfo = &info->UnauthAttrs;
3166 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3167 cItem++;
3169 items[cItem].pvStructInfo = &info->EncryptedHash;
3170 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
3171 cItem++;
3172 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3173 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3176 __EXCEPT_PAGE_FAULT
3178 SetLastError(STATUS_ACCESS_VIOLATION);
3180 __ENDTRY
3181 return ret;
3184 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3185 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
3186 void *pvEncoded, DWORD *pcbEncoded)
3188 static HCRYPTOIDFUNCSET set = NULL;
3189 BOOL ret = FALSE;
3190 CryptEncodeObjectExFunc encodeFunc = NULL;
3191 HCRYPTOIDFUNCADDR hFunc = NULL;
3193 TRACE("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
3194 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
3195 pvEncoded, pcbEncoded);
3197 if (!pvEncoded && !pcbEncoded)
3199 SetLastError(ERROR_INVALID_PARAMETER);
3200 return FALSE;
3202 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3203 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3205 SetLastError(ERROR_FILE_NOT_FOUND);
3206 return FALSE;
3209 SetLastError(NOERROR);
3210 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
3211 *(BYTE **)pvEncoded = NULL;
3212 if (!HIWORD(lpszStructType))
3214 switch (LOWORD(lpszStructType))
3216 case (WORD)X509_CERT:
3217 encodeFunc = CRYPT_AsnEncodeCert;
3218 break;
3219 case (WORD)X509_CERT_TO_BE_SIGNED:
3220 encodeFunc = CRYPT_AsnEncodeCertInfo;
3221 break;
3222 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
3223 encodeFunc = CRYPT_AsnEncodeCRLInfo;
3224 break;
3225 case (WORD)X509_EXTENSIONS:
3226 encodeFunc = CRYPT_AsnEncodeExtensions;
3227 break;
3228 case (WORD)X509_NAME_VALUE:
3229 encodeFunc = CRYPT_AsnEncodeNameValue;
3230 break;
3231 case (WORD)X509_NAME:
3232 encodeFunc = CRYPT_AsnEncodeName;
3233 break;
3234 case (WORD)X509_PUBLIC_KEY_INFO:
3235 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
3236 break;
3237 case (WORD)X509_AUTHORITY_KEY_ID:
3238 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3239 break;
3240 case (WORD)X509_ALTERNATE_NAME:
3241 encodeFunc = CRYPT_AsnEncodeAltName;
3242 break;
3243 case (WORD)X509_BASIC_CONSTRAINTS:
3244 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3245 break;
3246 case (WORD)X509_BASIC_CONSTRAINTS2:
3247 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3248 break;
3249 case (WORD)RSA_CSP_PUBLICKEYBLOB:
3250 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
3251 break;
3252 case (WORD)X509_UNICODE_NAME:
3253 encodeFunc = CRYPT_AsnEncodeUnicodeName;
3254 break;
3255 case (WORD)PKCS_CONTENT_INFO:
3256 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
3257 break;
3258 case (WORD)PKCS_ATTRIBUTE:
3259 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
3260 break;
3261 case (WORD)X509_UNICODE_NAME_VALUE:
3262 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
3263 break;
3264 case (WORD)X509_OCTET_STRING:
3265 encodeFunc = CRYPT_AsnEncodeOctets;
3266 break;
3267 case (WORD)X509_BITS:
3268 case (WORD)X509_KEY_USAGE:
3269 encodeFunc = CRYPT_AsnEncodeBits;
3270 break;
3271 case (WORD)X509_INTEGER:
3272 encodeFunc = CRYPT_AsnEncodeInt;
3273 break;
3274 case (WORD)X509_MULTI_BYTE_INTEGER:
3275 encodeFunc = CRYPT_AsnEncodeInteger;
3276 break;
3277 case (WORD)X509_MULTI_BYTE_UINT:
3278 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
3279 break;
3280 case (WORD)X509_ENUMERATED:
3281 encodeFunc = CRYPT_AsnEncodeEnumerated;
3282 break;
3283 case (WORD)X509_CHOICE_OF_TIME:
3284 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
3285 break;
3286 case (WORD)X509_AUTHORITY_KEY_ID2:
3287 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3288 break;
3289 case (WORD)X509_SEQUENCE_OF_ANY:
3290 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
3291 break;
3292 case (WORD)PKCS_UTC_TIME:
3293 encodeFunc = CRYPT_AsnEncodeUtcTime;
3294 break;
3295 case (WORD)X509_CRL_DIST_POINTS:
3296 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3297 break;
3298 case (WORD)X509_ENHANCED_KEY_USAGE:
3299 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3300 break;
3301 case (WORD)PKCS_ATTRIBUTES:
3302 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3303 break;
3304 case (WORD)X509_ISSUING_DIST_POINT:
3305 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3306 break;
3307 case (WORD)PKCS7_SIGNER_INFO:
3308 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
3309 break;
3310 default:
3311 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
3314 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3315 encodeFunc = CRYPT_AsnEncodeExtensions;
3316 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3317 encodeFunc = CRYPT_AsnEncodeUtcTime;
3318 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
3319 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3320 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
3321 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3322 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3323 encodeFunc = CRYPT_AsnEncodeEnumerated;
3324 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3325 encodeFunc = CRYPT_AsnEncodeBits;
3326 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3327 encodeFunc = CRYPT_AsnEncodeOctets;
3328 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3329 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3330 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3331 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3332 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3333 encodeFunc = CRYPT_AsnEncodeAltName;
3334 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3335 encodeFunc = CRYPT_AsnEncodeAltName;
3336 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3337 encodeFunc = CRYPT_AsnEncodeAltName;
3338 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3339 encodeFunc = CRYPT_AsnEncodeAltName;
3340 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3341 encodeFunc = CRYPT_AsnEncodeAltName;
3342 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3343 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3344 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3345 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3346 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3347 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3348 else
3349 TRACE("OID %s not found or unimplemented, looking for DLL\n",
3350 debugstr_a(lpszStructType));
3351 if (!encodeFunc)
3353 if (!set)
3354 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
3355 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3356 (void **)&encodeFunc, &hFunc);
3358 if (encodeFunc)
3359 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
3360 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
3361 else
3362 SetLastError(ERROR_FILE_NOT_FOUND);
3363 if (hFunc)
3364 CryptFreeOIDFunctionAddress(hFunc, 0);
3365 return ret;
3368 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV hCryptProv, DWORD dwKeySpec,
3369 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3371 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
3372 NULL, 0, NULL, pInfo, pcbInfo);
3375 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3376 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3377 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3379 BOOL ret;
3380 HCRYPTKEY key;
3381 static CHAR oid[] = szOID_RSA_RSA;
3383 TRACE("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv, dwKeySpec,
3384 dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo,
3385 pInfo, pcbInfo);
3387 if (!pszPublicKeyObjId)
3388 pszPublicKeyObjId = oid;
3389 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
3391 DWORD keySize = 0;
3393 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
3394 if (ret)
3396 LPBYTE pubKey = CryptMemAlloc(keySize);
3398 if (pubKey)
3400 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
3401 &keySize);
3402 if (ret)
3404 DWORD encodedLen = 0;
3406 ret = CryptEncodeObject(dwCertEncodingType,
3407 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
3408 if (ret)
3410 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
3411 strlen(pszPublicKeyObjId) + 1 + encodedLen;
3413 if (!pInfo)
3414 *pcbInfo = sizeNeeded;
3415 else if (*pcbInfo < sizeNeeded)
3417 SetLastError(ERROR_MORE_DATA);
3418 *pcbInfo = sizeNeeded;
3419 ret = FALSE;
3421 else
3423 pInfo->Algorithm.pszObjId = (char *)pInfo +
3424 sizeof(CERT_PUBLIC_KEY_INFO);
3425 lstrcpyA(pInfo->Algorithm.pszObjId,
3426 pszPublicKeyObjId);
3427 pInfo->Algorithm.Parameters.cbData = 0;
3428 pInfo->Algorithm.Parameters.pbData = NULL;
3429 pInfo->PublicKey.pbData =
3430 (BYTE *)pInfo->Algorithm.pszObjId
3431 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
3432 pInfo->PublicKey.cbData = encodedLen;
3433 pInfo->PublicKey.cUnusedBits = 0;
3434 ret = CryptEncodeObject(dwCertEncodingType,
3435 RSA_CSP_PUBLICKEYBLOB, pubKey,
3436 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
3440 CryptMemFree(pubKey);
3442 else
3443 ret = FALSE;
3445 CryptDestroyKey(key);
3447 return ret;
3450 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
3451 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3452 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
3454 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV hCryptProv, DWORD dwKeySpec,
3455 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
3456 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3458 static HCRYPTOIDFUNCSET set = NULL;
3459 BOOL ret;
3460 ExportPublicKeyInfoExFunc exportFunc = NULL;
3461 HCRYPTOIDFUNCADDR hFunc = NULL;
3463 TRACE("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv, dwKeySpec,
3464 dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo,
3465 pInfo, pcbInfo);
3467 if (!hCryptProv)
3469 SetLastError(ERROR_INVALID_PARAMETER);
3470 return FALSE;
3473 if (pszPublicKeyObjId)
3475 if (!set)
3476 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
3478 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
3479 0, (void **)&exportFunc, &hFunc);
3481 if (!exportFunc)
3482 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
3483 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
3484 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
3485 if (hFunc)
3486 CryptFreeOIDFunctionAddress(hFunc, 0);
3487 return ret;
3490 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
3491 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
3493 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
3494 0, 0, NULL, phKey);
3497 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3498 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3499 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3501 BOOL ret;
3502 DWORD pubKeySize = 0;
3504 TRACE("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv,
3505 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3507 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3508 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
3509 if (ret)
3511 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
3513 if (pubKey)
3515 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3516 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
3517 &pubKeySize);
3518 if (ret)
3519 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
3520 phKey);
3521 CryptMemFree(pubKey);
3523 else
3524 ret = FALSE;
3526 return ret;
3529 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
3530 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3531 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
3533 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3534 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3535 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3537 static HCRYPTOIDFUNCSET set = NULL;
3538 BOOL ret;
3539 ImportPublicKeyInfoExFunc importFunc = NULL;
3540 HCRYPTOIDFUNCADDR hFunc = NULL;
3542 TRACE("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv,
3543 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3545 if (!set)
3546 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
3547 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
3548 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
3549 if (!importFunc)
3550 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
3551 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
3552 pvAuxInfo, phKey);
3553 if (hFunc)
3554 CryptFreeOIDFunctionAddress(hFunc, 0);
3555 return ret;