crypt32: Include wine/port.h for snprintf().
[wine/multimedia.git] / dlls / crypt32 / encode.c
blobf769afcd76a88569756d188fd3eb6bc8681ed549
1 /*
2 * Copyright 2005-2007 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER encoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface isn't
21 * implemented, so I implement them here.
23 * References:
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
33 #include "config.h"
34 #include "wine/port.h"
36 #include <assert.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <stdlib.h>
41 #define NONAMELESSUNION
43 #include "windef.h"
44 #include "winbase.h"
45 #include "wincrypt.h"
46 #include "snmp.h"
47 #include "wine/debug.h"
48 #include "wine/exception.h"
49 #include "wine/unicode.h"
50 #include "crypt32_private.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
53 WINE_DECLARE_DEBUG_CHANNEL(crypt);
55 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
56 BYTE *, DWORD *);
58 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
59 * The dwCertEncodingType and lpszStructType are ignored by the built-in
60 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
61 * since it must call functions in external DLLs that follow these signatures.
63 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
64 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
65 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
66 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
67 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
68 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
69 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
70 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
71 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
72 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
73 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
74 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
75 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
76 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
77 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
78 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
79 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
80 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
81 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
82 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
83 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
84 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
85 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
86 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
87 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
88 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
89 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
90 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
91 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
92 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
93 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
94 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
95 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
97 BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
98 BYTE *pbEncoded, DWORD *pcbEncoded, DWORD bytesNeeded)
100 BOOL ret = TRUE;
102 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
104 if (pEncodePara && pEncodePara->pfnAlloc)
105 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
106 else
107 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
108 if (!*(BYTE **)pbEncoded)
109 ret = FALSE;
110 else
111 *pcbEncoded = bytesNeeded;
113 else if (bytesNeeded > *pcbEncoded)
115 *pcbEncoded = bytesNeeded;
116 SetLastError(ERROR_MORE_DATA);
117 ret = FALSE;
119 else
120 *pcbEncoded = bytesNeeded;
121 return ret;
124 BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
126 DWORD bytesNeeded, significantBytes = 0;
128 if (len <= 0x7f)
129 bytesNeeded = 1;
130 else
132 DWORD temp;
134 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
135 temp <<= 8, significantBytes--)
137 bytesNeeded = significantBytes + 1;
139 if (!pbEncoded)
141 *pcbEncoded = bytesNeeded;
142 return TRUE;
144 if (*pcbEncoded < bytesNeeded)
146 SetLastError(ERROR_MORE_DATA);
147 return FALSE;
149 if (len <= 0x7f)
150 *pbEncoded = (BYTE)len;
151 else
153 DWORD i;
155 *pbEncoded++ = significantBytes | 0x80;
156 for (i = 0; i < significantBytes; i++)
158 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
159 len >>= 8;
162 *pcbEncoded = bytesNeeded;
163 return TRUE;
166 BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
167 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
168 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
170 BOOL ret;
171 DWORD i, dataLen = 0;
173 TRACE("%p, %d, %08x, %p, %p, %d\n", items, cItem, dwFlags, pEncodePara,
174 pbEncoded, *pcbEncoded);
175 for (i = 0, ret = TRUE; ret && i < cItem; i++)
177 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
178 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
179 NULL, &items[i].size);
180 /* Some functions propagate their errors through the size */
181 if (!ret)
182 *pcbEncoded = items[i].size;
183 dataLen += items[i].size;
185 if (ret)
187 DWORD lenBytes, bytesNeeded;
189 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
190 bytesNeeded = 1 + lenBytes + dataLen;
191 if (!pbEncoded)
192 *pcbEncoded = bytesNeeded;
193 else
195 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
196 pcbEncoded, bytesNeeded)))
198 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
199 pbEncoded = *(BYTE **)pbEncoded;
200 *pbEncoded++ = ASN_SEQUENCE;
201 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
202 pbEncoded += lenBytes;
203 for (i = 0; ret && i < cItem; i++)
205 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
206 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
207 NULL, pbEncoded, &items[i].size);
208 /* Some functions propagate their errors through the size */
209 if (!ret)
210 *pcbEncoded = items[i].size;
211 pbEncoded += items[i].size;
216 TRACE("returning %d (%08x)\n", ret, GetLastError());
217 return ret;
220 BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
221 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
222 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
224 BOOL ret;
225 const struct AsnConstructedItem *item =
226 (const struct AsnConstructedItem *)pvStructInfo;
227 DWORD len;
229 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
230 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
232 DWORD dataLen, bytesNeeded;
234 CRYPT_EncodeLen(len, NULL, &dataLen);
235 bytesNeeded = 1 + dataLen + len;
236 if (!pbEncoded)
237 *pcbEncoded = bytesNeeded;
238 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
239 pbEncoded, pcbEncoded, bytesNeeded)))
241 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
242 pbEncoded = *(BYTE **)pbEncoded;
243 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
244 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
245 pbEncoded += dataLen;
246 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
247 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
248 pbEncoded, &len);
249 if (!ret)
251 /* Some functions propagate their errors through the size */
252 *pcbEncoded = len;
256 else
258 /* Some functions propagate their errors through the size */
259 *pcbEncoded = len;
261 return ret;
264 struct AsnEncodeTagSwappedItem
266 BYTE tag;
267 const void *pvStructInfo;
268 CryptEncodeObjectExFunc encodeFunc;
271 /* Sort of a wacky hack, it encodes something using the struct
272 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
273 * given in the struct AsnEncodeTagSwappedItem.
275 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
276 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
277 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
279 BOOL ret;
280 const struct AsnEncodeTagSwappedItem *item =
281 (const struct AsnEncodeTagSwappedItem *)pvStructInfo;
283 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
284 item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
285 if (ret && pbEncoded)
286 *pbEncoded = item->tag;
287 return ret;
290 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
291 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
292 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
294 const DWORD *ver = (const DWORD *)pvStructInfo;
295 BOOL ret;
297 /* CERT_V1 is not encoded */
298 if (*ver == CERT_V1)
300 *pcbEncoded = 0;
301 ret = TRUE;
303 else
305 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
307 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
308 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
310 return ret;
313 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
314 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
315 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
317 const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
318 BOOL ret;
320 if (!pbEncoded)
322 *pcbEncoded = blob->cbData;
323 ret = TRUE;
325 else
327 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
328 pcbEncoded, blob->cbData)))
330 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
331 pbEncoded = *(BYTE **)pbEncoded;
332 if (blob->cbData)
333 memcpy(pbEncoded, blob->pbData, blob->cbData);
334 *pcbEncoded = blob->cbData;
335 ret = TRUE;
338 return ret;
341 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
342 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
343 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
345 BOOL ret;
346 /* This has two filetimes in a row, a NotBefore and a NotAfter */
347 const FILETIME *timePtr = (const FILETIME *)pvStructInfo;
348 struct AsnEncodeSequenceItem items[] = {
349 { timePtr++, CRYPT_AsnEncodeChoiceOfTime, 0 },
350 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
353 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
354 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
355 pcbEncoded);
356 return ret;
359 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
360 * if they are empty.
362 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
363 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
364 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
365 DWORD *pcbEncoded)
367 const CRYPT_ALGORITHM_IDENTIFIER *algo =
368 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
369 static const BYTE asn1Null[] = { ASN_NULL, 0 };
370 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
371 (LPBYTE)asn1Null };
372 BOOL ret;
373 struct AsnEncodeSequenceItem items[2] = {
374 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
375 { NULL, CRYPT_CopyEncodedBlob, 0 },
378 if (algo->Parameters.cbData)
379 items[1].pvStructInfo = &algo->Parameters;
380 else
381 items[1].pvStructInfo = &nullBlob;
382 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
383 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
384 pcbEncoded);
385 return ret;
388 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType,
389 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
390 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
392 const CRYPT_ALGORITHM_IDENTIFIER *algo =
393 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
394 BOOL ret;
395 struct AsnEncodeSequenceItem items[] = {
396 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
397 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
400 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
401 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
402 pcbEncoded);
403 return ret;
406 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
407 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
408 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
410 BOOL ret;
412 __TRY
414 const CERT_PUBLIC_KEY_INFO *info =
415 (const CERT_PUBLIC_KEY_INFO *)pvStructInfo;
416 struct AsnEncodeSequenceItem items[] = {
417 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
418 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
421 TRACE("Encoding public key with OID %s\n",
422 debugstr_a(info->Algorithm.pszObjId));
423 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
424 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
425 pcbEncoded);
427 __EXCEPT_PAGE_FAULT
429 SetLastError(STATUS_ACCESS_VIOLATION);
430 ret = FALSE;
432 __ENDTRY
433 return ret;
436 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
437 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
438 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
440 BOOL ret;
442 __TRY
444 const CERT_SIGNED_CONTENT_INFO *info =
445 (const CERT_SIGNED_CONTENT_INFO *)pvStructInfo;
446 struct AsnEncodeSequenceItem items[] = {
447 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
448 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
449 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
452 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
453 items[2].encodeFunc = CRYPT_AsnEncodeBits;
454 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
455 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
456 pcbEncoded);
458 __EXCEPT_PAGE_FAULT
460 SetLastError(STATUS_ACCESS_VIOLATION);
461 ret = FALSE;
463 __ENDTRY
464 return ret;
467 /* Like in Windows, this blithely ignores the validity of the passed-in
468 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
469 * decode properly, see CRYPT_AsnDecodeCertInfo.
471 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
472 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
473 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
475 BOOL ret;
477 __TRY
479 const CERT_INFO *info = (const CERT_INFO *)pvStructInfo;
480 struct AsnEncodeSequenceItem items[10] = {
481 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
482 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
483 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
484 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
485 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
486 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
487 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfo, 0 },
488 { 0 }
490 struct AsnConstructedItem constructed[3] = { { 0 } };
491 DWORD cItem = 7, cConstructed = 0;
493 if (info->IssuerUniqueId.cbData)
495 constructed[cConstructed].tag = 1;
496 constructed[cConstructed].pvStructInfo = &info->IssuerUniqueId;
497 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
498 items[cItem].pvStructInfo = &constructed[cConstructed];
499 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
500 cConstructed++;
501 cItem++;
503 if (info->SubjectUniqueId.cbData)
505 constructed[cConstructed].tag = 2;
506 constructed[cConstructed].pvStructInfo = &info->SubjectUniqueId;
507 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
508 items[cItem].pvStructInfo = &constructed[cConstructed];
509 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
510 cConstructed++;
511 cItem++;
513 if (info->cExtension)
515 constructed[cConstructed].tag = 3;
516 constructed[cConstructed].pvStructInfo = &info->cExtension;
517 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
518 items[cItem].pvStructInfo = &constructed[cConstructed];
519 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
520 cConstructed++;
521 cItem++;
524 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
525 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
527 __EXCEPT_PAGE_FAULT
529 SetLastError(STATUS_ACCESS_VIOLATION);
530 ret = FALSE;
532 __ENDTRY
533 return ret;
536 static BOOL WINAPI CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
537 BYTE *pbEncoded, DWORD *pcbEncoded)
539 struct AsnEncodeSequenceItem items[3] = {
540 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
541 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
542 { 0 }
544 DWORD cItem = 2;
545 BOOL ret;
547 TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded);
549 if (entry->cExtension)
551 items[cItem].pvStructInfo = &entry->cExtension;
552 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
553 cItem++;
556 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
557 pbEncoded, pcbEncoded);
559 TRACE("returning %d (%08x)\n", ret, GetLastError());
560 return ret;
563 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
564 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
565 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
567 DWORD cCRLEntry = *(const DWORD *)pvStructInfo;
568 DWORD bytesNeeded, dataLen, lenBytes, i;
569 const CRL_ENTRY *rgCRLEntry = *(const CRL_ENTRY *const *)
570 ((const BYTE *)pvStructInfo + sizeof(DWORD));
571 BOOL ret = TRUE;
573 for (i = 0, dataLen = 0; ret && i < cCRLEntry; i++)
575 DWORD size;
577 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
578 if (ret)
579 dataLen += size;
581 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
582 bytesNeeded = 1 + lenBytes + dataLen;
583 if (!pbEncoded)
584 *pcbEncoded = bytesNeeded;
585 else
587 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
588 pcbEncoded, bytesNeeded)))
590 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
591 pbEncoded = *(BYTE **)pbEncoded;
592 *pbEncoded++ = ASN_SEQUENCEOF;
593 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
594 pbEncoded += lenBytes;
595 for (i = 0; i < cCRLEntry; i++)
597 DWORD size = dataLen;
599 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], pbEncoded, &size);
600 pbEncoded += size;
601 dataLen -= size;
605 return ret;
608 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
609 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
610 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
612 const DWORD *ver = (const DWORD *)pvStructInfo;
613 BOOL ret;
615 /* CRL_V1 is not encoded */
616 if (*ver == CRL_V1)
618 *pcbEncoded = 0;
619 ret = TRUE;
621 else
622 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
623 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
624 return ret;
627 /* Like in Windows, this blithely ignores the validity of the passed-in
628 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
629 * decode properly, see CRYPT_AsnDecodeCRLInfo.
631 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
632 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
633 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
635 BOOL ret;
637 __TRY
639 const CRL_INFO *info = (const CRL_INFO *)pvStructInfo;
640 struct AsnEncodeSequenceItem items[7] = {
641 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
642 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
643 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
644 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
645 { 0 }
647 struct AsnConstructedItem constructed[1] = { { 0 } };
648 DWORD cItem = 4, cConstructed = 0;
650 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
652 items[cItem].pvStructInfo = &info->NextUpdate;
653 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
654 cItem++;
656 if (info->cCRLEntry)
658 items[cItem].pvStructInfo = &info->cCRLEntry;
659 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
660 cItem++;
662 if (info->cExtension)
664 constructed[cConstructed].tag = 0;
665 constructed[cConstructed].pvStructInfo = &info->cExtension;
666 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
667 items[cItem].pvStructInfo = &constructed[cConstructed];
668 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
669 cConstructed++;
670 cItem++;
673 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
674 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
676 __EXCEPT_PAGE_FAULT
678 SetLastError(STATUS_ACCESS_VIOLATION);
679 ret = FALSE;
681 __ENDTRY
682 return ret;
685 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
686 DWORD *pcbEncoded)
688 BOOL ret;
689 struct AsnEncodeSequenceItem items[3] = {
690 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
691 { NULL, NULL, 0 },
692 { NULL, NULL, 0 },
694 DWORD cItem = 1;
696 TRACE("%p, %p, %d\n", ext, pbEncoded, *pcbEncoded);
698 if (ext->fCritical)
700 items[cItem].pvStructInfo = &ext->fCritical;
701 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
702 cItem++;
704 items[cItem].pvStructInfo = &ext->Value;
705 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
706 cItem++;
708 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
709 pbEncoded, pcbEncoded);
710 TRACE("returning %d (%08x)\n", ret, GetLastError());
711 return ret;
714 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
715 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
716 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
718 BOOL ret;
720 __TRY
722 DWORD bytesNeeded, dataLen, lenBytes, i;
723 const CERT_EXTENSIONS *exts = (const CERT_EXTENSIONS *)pvStructInfo;
725 ret = TRUE;
726 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
728 DWORD size;
730 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
731 if (ret)
732 dataLen += size;
734 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
735 bytesNeeded = 1 + lenBytes + dataLen;
736 if (!pbEncoded)
737 *pcbEncoded = bytesNeeded;
738 else
740 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
741 pcbEncoded, bytesNeeded)))
743 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
744 pbEncoded = *(BYTE **)pbEncoded;
745 *pbEncoded++ = ASN_SEQUENCEOF;
746 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
747 pbEncoded += lenBytes;
748 for (i = 0; i < exts->cExtension; i++)
750 DWORD size = dataLen;
752 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
753 pbEncoded, &size);
754 pbEncoded += size;
755 dataLen -= size;
760 __EXCEPT_PAGE_FAULT
762 SetLastError(STATUS_ACCESS_VIOLATION);
763 ret = FALSE;
765 __ENDTRY
766 return ret;
769 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
770 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
771 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
773 LPCSTR pszObjId = (LPCSTR)pvStructInfo;
774 DWORD bytesNeeded = 0, lenBytes;
775 BOOL ret = TRUE;
776 int firstPos = 0;
777 BYTE firstByte = 0;
779 TRACE("%s\n", debugstr_a(pszObjId));
781 if (pszObjId)
783 const char *ptr;
784 int val1, val2;
786 if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
788 SetLastError(CRYPT_E_ASN1_ERROR);
789 return FALSE;
791 bytesNeeded++;
792 firstByte = val1 * 40 + val2;
793 ptr = pszObjId + firstPos;
794 while (ret && *ptr)
796 int pos;
798 /* note I assume each component is at most 32-bits long in base 2 */
799 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
801 if (val1 >= 0x10000000)
802 bytesNeeded += 5;
803 else if (val1 >= 0x200000)
804 bytesNeeded += 4;
805 else if (val1 >= 0x4000)
806 bytesNeeded += 3;
807 else if (val1 >= 0x80)
808 bytesNeeded += 2;
809 else
810 bytesNeeded += 1;
811 ptr += pos;
812 if (*ptr == '.')
813 ptr++;
815 else
817 SetLastError(CRYPT_E_ASN1_ERROR);
818 return FALSE;
821 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
823 else
824 lenBytes = 1;
825 bytesNeeded += 1 + lenBytes;
826 if (pbEncoded)
828 if (*pcbEncoded < bytesNeeded)
830 SetLastError(ERROR_MORE_DATA);
831 ret = FALSE;
833 else
835 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
836 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
837 pbEncoded += lenBytes;
838 if (pszObjId)
840 const char *ptr;
841 int val, pos;
843 *pbEncoded++ = firstByte;
844 ptr = pszObjId + firstPos;
845 while (ret && *ptr)
847 sscanf(ptr, "%d%n", &val, &pos);
849 unsigned char outBytes[5];
850 int numBytes, i;
852 if (val >= 0x10000000)
853 numBytes = 5;
854 else if (val >= 0x200000)
855 numBytes = 4;
856 else if (val >= 0x4000)
857 numBytes = 3;
858 else if (val >= 0x80)
859 numBytes = 2;
860 else
861 numBytes = 1;
862 for (i = numBytes; i > 0; i--)
864 outBytes[i - 1] = val & 0x7f;
865 val >>= 7;
867 for (i = 0; i < numBytes - 1; i++)
868 *pbEncoded++ = outBytes[i] | 0x80;
869 *pbEncoded++ = outBytes[i];
870 ptr += pos;
871 if (*ptr == '.')
872 ptr++;
878 *pcbEncoded = bytesNeeded;
879 return ret;
882 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
883 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
884 DWORD *pcbEncoded)
886 BOOL ret = TRUE;
887 LPCSTR str = (LPCSTR)value->Value.pbData;
888 DWORD bytesNeeded, lenBytes, encodedLen;
890 encodedLen = value->Value.cbData ? value->Value.cbData : lstrlenA(str);
891 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
892 bytesNeeded = 1 + lenBytes + encodedLen;
893 if (!pbEncoded)
894 *pcbEncoded = bytesNeeded;
895 else
897 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
898 pbEncoded, pcbEncoded, bytesNeeded)))
900 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
901 pbEncoded = *(BYTE **)pbEncoded;
902 *pbEncoded++ = tag;
903 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
904 pbEncoded += lenBytes;
905 memcpy(pbEncoded, str, encodedLen);
908 return ret;
911 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
912 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
913 DWORD *pcbEncoded)
915 BOOL ret = TRUE;
916 LPCWSTR str = (LPCWSTR)value->Value.pbData;
917 DWORD bytesNeeded, lenBytes, strLen;
919 if (value->Value.cbData)
920 strLen = value->Value.cbData / sizeof(WCHAR);
921 else if (value->Value.pbData)
922 strLen = lstrlenW(str);
923 else
924 strLen = 0;
925 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
926 bytesNeeded = 1 + lenBytes + strLen * 2;
927 if (!pbEncoded)
928 *pcbEncoded = bytesNeeded;
929 else
931 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
932 pbEncoded, pcbEncoded, bytesNeeded)))
934 DWORD i;
936 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
937 pbEncoded = *(BYTE **)pbEncoded;
938 *pbEncoded++ = ASN_BMPSTRING;
939 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
940 pbEncoded += lenBytes;
941 for (i = 0; i < strLen; i++)
943 *pbEncoded++ = (str[i] & 0xff00) >> 8;
944 *pbEncoded++ = str[i] & 0x00ff;
948 return ret;
951 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
952 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
953 DWORD *pcbEncoded)
955 BOOL ret = TRUE;
956 LPCWSTR str = (LPCWSTR)value->Value.pbData;
957 DWORD bytesNeeded, lenBytes, encodedLen, strLen;
959 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
960 lstrlenW(str);
961 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
962 NULL);
963 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
964 bytesNeeded = 1 + lenBytes + encodedLen;
965 if (!pbEncoded)
966 *pcbEncoded = bytesNeeded;
967 else
969 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
970 pbEncoded, pcbEncoded, bytesNeeded)))
972 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
973 pbEncoded = *(BYTE **)pbEncoded;
974 *pbEncoded++ = ASN_UTF8STRING;
975 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
976 pbEncoded += lenBytes;
977 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
978 bytesNeeded - lenBytes - 1, NULL, NULL);
981 return ret;
984 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
985 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
986 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
988 BOOL ret = TRUE;
990 __TRY
992 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
994 switch (value->dwValueType)
996 case CERT_RDN_ANY_TYPE:
997 /* explicitly disallowed */
998 SetLastError(E_INVALIDARG);
999 ret = FALSE;
1000 break;
1001 case CERT_RDN_ENCODED_BLOB:
1002 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
1003 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1004 break;
1005 case CERT_RDN_OCTET_STRING:
1006 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1007 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1008 break;
1009 case CERT_RDN_NUMERIC_STRING:
1010 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1011 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1012 break;
1013 case CERT_RDN_PRINTABLE_STRING:
1014 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1015 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1016 break;
1017 case CERT_RDN_TELETEX_STRING:
1018 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1019 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1020 break;
1021 case CERT_RDN_VIDEOTEX_STRING:
1022 ret = CRYPT_AsnEncodeStringCoerce(value,
1023 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1024 break;
1025 case CERT_RDN_IA5_STRING:
1026 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1027 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1028 break;
1029 case CERT_RDN_GRAPHIC_STRING:
1030 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1031 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1032 break;
1033 case CERT_RDN_VISIBLE_STRING:
1034 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1035 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1036 break;
1037 case CERT_RDN_GENERAL_STRING:
1038 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1039 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1040 break;
1041 case CERT_RDN_UNIVERSAL_STRING:
1042 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1043 SetLastError(CRYPT_E_ASN1_CHOICE);
1044 ret = FALSE;
1045 break;
1046 case CERT_RDN_BMP_STRING:
1047 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1048 pbEncoded, pcbEncoded);
1049 break;
1050 case CERT_RDN_UTF8_STRING:
1051 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1052 pbEncoded, pcbEncoded);
1053 break;
1054 default:
1055 SetLastError(CRYPT_E_ASN1_CHOICE);
1056 ret = FALSE;
1059 __EXCEPT_PAGE_FAULT
1061 SetLastError(STATUS_ACCESS_VIOLATION);
1062 ret = FALSE;
1064 __ENDTRY
1065 return ret;
1068 static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1069 CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1070 BYTE *pbEncoded, DWORD *pcbEncoded)
1072 DWORD bytesNeeded = 0, lenBytes, size;
1073 BOOL ret;
1075 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1076 0, NULL, NULL, &size);
1077 if (ret)
1079 bytesNeeded += size;
1080 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1081 * with dwValueType, so "cast" it to get its encoded size
1083 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1084 (CERT_NAME_VALUE *)&attr->dwValueType, 0, NULL, NULL, &size);
1085 if (ret)
1087 bytesNeeded += size;
1088 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1089 bytesNeeded += 1 + lenBytes;
1090 if (pbEncoded)
1092 if (*pcbEncoded < bytesNeeded)
1094 SetLastError(ERROR_MORE_DATA);
1095 ret = FALSE;
1097 else
1099 *pbEncoded++ = ASN_SEQUENCE;
1100 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1101 &lenBytes);
1102 pbEncoded += lenBytes;
1103 size = bytesNeeded - 1 - lenBytes;
1104 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1105 attr->pszObjId, 0, NULL, pbEncoded, &size);
1106 if (ret)
1108 pbEncoded += size;
1109 size = bytesNeeded - 1 - lenBytes - size;
1110 ret = nameValueEncodeFunc(dwCertEncodingType,
1111 NULL, (CERT_NAME_VALUE *)&attr->dwValueType,
1112 0, NULL, pbEncoded, &size);
1113 if (!ret)
1114 *pcbEncoded = size;
1118 if (ret)
1119 *pcbEncoded = bytesNeeded;
1121 else
1123 /* Have to propagate index of failing character */
1124 *pcbEncoded = size;
1127 return ret;
1130 static int BLOBComp(const void *l, const void *r)
1132 const CRYPT_DER_BLOB *a = (const CRYPT_DER_BLOB *)l, *b = (const CRYPT_DER_BLOB *)r;
1133 int ret;
1135 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1136 ret = a->cbData - b->cbData;
1137 return ret;
1140 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1142 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1143 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1144 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1146 const CRYPT_BLOB_ARRAY *set = (const CRYPT_BLOB_ARRAY *)pvStructInfo;
1147 DWORD bytesNeeded = 0, lenBytes, i;
1148 BOOL ret;
1150 for (i = 0; i < set->cBlob; i++)
1151 bytesNeeded += set->rgBlob[i].cbData;
1152 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1153 bytesNeeded += 1 + lenBytes;
1154 if (!pbEncoded)
1156 *pcbEncoded = bytesNeeded;
1157 ret = TRUE;
1159 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1160 pbEncoded, pcbEncoded, bytesNeeded)))
1162 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1163 pbEncoded = *(BYTE **)pbEncoded;
1164 qsort(set->rgBlob, set->cBlob, sizeof(CRYPT_DER_BLOB), BLOBComp);
1165 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1166 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1167 pbEncoded += lenBytes;
1168 for (i = 0; ret && i < set->cBlob; i++)
1170 memcpy(pbEncoded, set->rgBlob[i].pbData, set->rgBlob[i].cbData);
1171 pbEncoded += set->rgBlob[i].cbData;
1174 return ret;
1177 struct DERSetDescriptor
1179 DWORD cItems;
1180 const void *items;
1181 size_t itemSize;
1182 size_t itemOffset;
1183 CryptEncodeObjectExFunc encode;
1186 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,
1187 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1188 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1190 const struct DERSetDescriptor *desc =
1191 (const struct DERSetDescriptor *)pvStructInfo;
1192 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1193 BOOL ret = TRUE;
1194 DWORD i;
1196 if (desc->cItems)
1198 setOf.rgBlob = CryptMemAlloc(desc->cItems * sizeof(CRYPT_DER_BLOB));
1199 if (!setOf.rgBlob)
1200 ret = FALSE;
1201 else
1203 setOf.cBlob = desc->cItems;
1204 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1207 for (i = 0; ret && i < setOf.cBlob; i++)
1209 ret = desc->encode(dwCertEncodingType, lpszStructType,
1210 (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
1211 0, NULL, NULL, &setOf.rgBlob[i].cbData);
1212 if (ret)
1214 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1215 if (!setOf.rgBlob[i].pbData)
1216 ret = FALSE;
1217 else
1218 ret = desc->encode(dwCertEncodingType, lpszStructType,
1219 (const BYTE *)desc->items + i * desc->itemSize +
1220 desc->itemOffset, 0, NULL, setOf.rgBlob[i].pbData,
1221 &setOf.rgBlob[i].cbData);
1223 /* Some functions propagate their errors through the size */
1224 if (!ret)
1225 *pcbEncoded = setOf.rgBlob[i].cbData;
1227 if (ret)
1229 DWORD bytesNeeded = 0, lenBytes;
1230 BOOL ret;
1232 for (i = 0; i < setOf.cBlob; i++)
1233 bytesNeeded += setOf.rgBlob[i].cbData;
1234 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1235 bytesNeeded += 1 + lenBytes;
1236 if (!pbEncoded)
1237 *pcbEncoded = bytesNeeded;
1238 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1239 pbEncoded, pcbEncoded, bytesNeeded)))
1241 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1242 pbEncoded = *(BYTE **)pbEncoded;
1243 qsort(setOf.rgBlob, setOf.cBlob, sizeof(CRYPT_DER_BLOB),
1244 BLOBComp);
1245 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1246 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1247 pbEncoded += lenBytes;
1248 for (i = 0; i < setOf.cBlob; i++)
1250 memcpy(pbEncoded, setOf.rgBlob[i].pbData,
1251 setOf.rgBlob[i].cbData);
1252 pbEncoded += setOf.rgBlob[i].cbData;
1256 for (i = 0; i < setOf.cBlob; i++)
1257 CryptMemFree(setOf.rgBlob[i].pbData);
1258 CryptMemFree(setOf.rgBlob);
1259 return ret;
1262 static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
1263 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1264 DWORD *pcbEncoded)
1266 BOOL ret;
1267 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1269 __TRY
1271 DWORD i;
1273 ret = TRUE;
1274 if (rdn->cRDNAttr)
1276 setOf.cBlob = rdn->cRDNAttr;
1277 setOf.rgBlob = CryptMemAlloc(rdn->cRDNAttr *
1278 sizeof(CRYPT_DER_BLOB));
1279 if (!setOf.rgBlob)
1280 ret = FALSE;
1281 else
1282 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1284 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1286 setOf.rgBlob[i].cbData = 0;
1287 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1288 nameValueEncodeFunc, NULL, &setOf.rgBlob[i].cbData);
1289 if (ret)
1291 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1292 if (!setOf.rgBlob[i].pbData)
1293 ret = FALSE;
1294 else
1295 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1296 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1297 setOf.rgBlob[i].pbData, &setOf.rgBlob[i].cbData);
1299 if (!ret)
1301 /* Have to propagate index of failing character */
1302 *pcbEncoded = setOf.rgBlob[i].cbData;
1305 if (ret)
1306 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1307 pbEncoded, pcbEncoded);
1308 for (i = 0; i < setOf.cBlob; i++)
1309 CryptMemFree(setOf.rgBlob[i].pbData);
1311 __EXCEPT_PAGE_FAULT
1313 SetLastError(STATUS_ACCESS_VIOLATION);
1314 ret = FALSE;
1316 __ENDTRY
1317 CryptMemFree(setOf.rgBlob);
1318 return ret;
1321 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1322 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1323 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1325 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1326 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1327 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1328 DWORD *pcbEncoded)
1330 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1331 BOOL ret;
1333 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1334 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1335 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1336 else
1337 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1338 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1339 return ret;
1342 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1343 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1344 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1346 BOOL ret = TRUE;
1348 __TRY
1350 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1351 DWORD bytesNeeded = 0, lenBytes, size, i;
1353 TRACE("encoding name with %d RDNs\n", info->cRDN);
1354 ret = TRUE;
1355 for (i = 0; ret && i < info->cRDN; i++)
1357 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1358 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1359 if (ret)
1360 bytesNeeded += size;
1361 else
1362 *pcbEncoded = size;
1364 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1365 bytesNeeded += 1 + lenBytes;
1366 if (ret)
1368 if (!pbEncoded)
1369 *pcbEncoded = bytesNeeded;
1370 else
1372 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1373 pbEncoded, pcbEncoded, bytesNeeded)))
1375 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1376 pbEncoded = *(BYTE **)pbEncoded;
1377 *pbEncoded++ = ASN_SEQUENCEOF;
1378 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1379 &lenBytes);
1380 pbEncoded += lenBytes;
1381 for (i = 0; ret && i < info->cRDN; i++)
1383 size = bytesNeeded;
1384 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1385 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1386 pbEncoded, &size);
1387 if (ret)
1389 pbEncoded += size;
1390 bytesNeeded -= size;
1392 else
1393 *pcbEncoded = size;
1399 __EXCEPT_PAGE_FAULT
1401 SetLastError(STATUS_ACCESS_VIOLATION);
1402 ret = FALSE;
1404 __ENDTRY
1405 return ret;
1408 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1409 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1410 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1412 BOOL ret = FALSE;
1414 __TRY
1416 const CRYPT_ATTRIBUTE *attr = (const CRYPT_ATTRIBUTE *)pvStructInfo;
1418 if (!attr->pszObjId)
1419 SetLastError(E_INVALIDARG);
1420 else
1422 struct AsnEncodeSequenceItem items[2] = {
1423 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1424 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1427 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1428 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1429 pcbEncoded);
1432 __EXCEPT_PAGE_FAULT
1434 SetLastError(STATUS_ACCESS_VIOLATION);
1436 __ENDTRY
1437 return ret;
1440 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1441 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1442 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1444 BOOL ret = FALSE;
1446 __TRY
1448 const CRYPT_ATTRIBUTES *attributes =
1449 (const CRYPT_ATTRIBUTES *)pvStructInfo;
1450 struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
1451 sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
1453 ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
1454 &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1456 __EXCEPT_PAGE_FAULT
1458 SetLastError(STATUS_ACCESS_VIOLATION);
1460 __ENDTRY
1461 return ret;
1464 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1465 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
1466 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1467 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1468 DWORD *pcbEncoded)
1470 const CRYPT_CONTENT_INFO *info = (const CRYPT_CONTENT_INFO *)pvStructInfo;
1471 struct AsnEncodeSequenceItem items[2] = {
1472 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1473 { NULL, NULL, 0 },
1475 struct AsnConstructedItem constructed = { 0 };
1476 DWORD cItem = 1;
1478 if (info->Content.cbData)
1480 constructed.tag = 0;
1481 constructed.pvStructInfo = &info->Content;
1482 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1483 items[cItem].pvStructInfo = &constructed;
1484 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1485 cItem++;
1487 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1488 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1491 BOOL CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA *digestedData,
1492 void *pvData, DWORD *pcbData)
1494 struct AsnEncodeSequenceItem items[] = {
1495 { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1496 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
1497 0 },
1498 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1499 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1502 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1503 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
1506 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1507 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1508 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1510 BOOL ret = FALSE;
1512 __TRY
1514 const CRYPT_CONTENT_INFO *info =
1515 (const CRYPT_CONTENT_INFO *)pvStructInfo;
1517 if (!info->pszObjId)
1518 SetLastError(E_INVALIDARG);
1519 else
1520 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
1521 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1522 pcbEncoded);
1524 __EXCEPT_PAGE_FAULT
1526 SetLastError(STATUS_ACCESS_VIOLATION);
1528 __ENDTRY
1529 return ret;
1532 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1533 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1534 DWORD *pcbEncoded)
1536 BOOL ret = TRUE;
1537 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1538 DWORD bytesNeeded, lenBytes, encodedLen;
1540 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1541 lstrlenW(str);
1542 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1543 bytesNeeded = 1 + lenBytes + encodedLen;
1544 if (!pbEncoded)
1545 *pcbEncoded = bytesNeeded;
1546 else
1548 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1549 pbEncoded, pcbEncoded, bytesNeeded)))
1551 DWORD i;
1553 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1554 pbEncoded = *(BYTE **)pbEncoded;
1555 *pbEncoded++ = tag;
1556 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1557 pbEncoded += lenBytes;
1558 for (i = 0; i < encodedLen; i++)
1559 *pbEncoded++ = (BYTE)str[i];
1562 return ret;
1565 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
1566 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1567 DWORD *pcbEncoded)
1569 BOOL ret = TRUE;
1570 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1571 DWORD bytesNeeded, lenBytes, encodedLen;
1573 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1574 lstrlenW(str);
1575 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1576 bytesNeeded = 1 + lenBytes + encodedLen;
1577 if (!pbEncoded)
1578 *pcbEncoded = bytesNeeded;
1579 else
1581 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1582 pbEncoded, pcbEncoded, bytesNeeded)))
1584 DWORD i;
1585 BYTE *ptr;
1587 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1588 ptr = *(BYTE **)pbEncoded;
1589 else
1590 ptr = pbEncoded;
1591 *ptr++ = ASN_NUMERICSTRING;
1592 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
1593 ptr += lenBytes;
1594 for (i = 0; ret && i < encodedLen; i++)
1596 if (isdigitW(str[i]))
1597 *ptr++ = (BYTE)str[i];
1598 else
1600 *pcbEncoded = i;
1601 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
1602 ret = FALSE;
1605 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1606 CryptMemFree(*(BYTE **)pbEncoded);
1609 return ret;
1612 static inline int isprintableW(WCHAR wc)
1614 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
1615 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
1616 wc == '/' || wc == ':' || wc == '=' || wc == '?';
1619 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
1620 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1621 DWORD *pcbEncoded)
1623 BOOL ret = TRUE;
1624 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1625 DWORD bytesNeeded, lenBytes, encodedLen;
1627 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1628 lstrlenW(str);
1629 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1630 bytesNeeded = 1 + lenBytes + encodedLen;
1631 if (!pbEncoded)
1632 *pcbEncoded = bytesNeeded;
1633 else
1635 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1636 pbEncoded, pcbEncoded, bytesNeeded)))
1638 DWORD i;
1639 BYTE *ptr;
1641 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1642 ptr = *(BYTE **)pbEncoded;
1643 else
1644 ptr = pbEncoded;
1645 *ptr++ = ASN_PRINTABLESTRING;
1646 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
1647 ptr += lenBytes;
1648 for (i = 0; ret && i < encodedLen; i++)
1650 if (isprintableW(str[i]))
1651 *ptr++ = (BYTE)str[i];
1652 else
1654 *pcbEncoded = i;
1655 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
1656 ret = FALSE;
1659 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1660 CryptMemFree(*(BYTE **)pbEncoded);
1663 return ret;
1666 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
1667 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1668 DWORD *pcbEncoded)
1670 BOOL ret = TRUE;
1671 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1672 DWORD bytesNeeded, lenBytes, encodedLen;
1674 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1675 lstrlenW(str);
1676 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1677 bytesNeeded = 1 + lenBytes + encodedLen;
1678 if (!pbEncoded)
1679 *pcbEncoded = bytesNeeded;
1680 else
1682 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1683 pbEncoded, pcbEncoded, bytesNeeded)))
1685 DWORD i;
1686 BYTE *ptr;
1688 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1689 ptr = *(BYTE **)pbEncoded;
1690 else
1691 ptr = pbEncoded;
1692 *ptr++ = ASN_IA5STRING;
1693 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
1694 ptr += lenBytes;
1695 for (i = 0; ret && i < encodedLen; i++)
1697 if (str[i] <= 0x7f)
1698 *ptr++ = (BYTE)str[i];
1699 else
1701 *pcbEncoded = i;
1702 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1703 ret = FALSE;
1706 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1707 CryptMemFree(*(BYTE **)pbEncoded);
1710 return ret;
1713 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
1714 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1715 DWORD *pcbEncoded)
1717 BOOL ret = TRUE;
1718 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1719 DWORD bytesNeeded, lenBytes, strLen;
1721 /* FIXME: doesn't handle composite characters */
1722 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1723 lstrlenW(str);
1724 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
1725 bytesNeeded = 1 + lenBytes + strLen * 4;
1726 if (!pbEncoded)
1727 *pcbEncoded = bytesNeeded;
1728 else
1730 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1731 pbEncoded, pcbEncoded, bytesNeeded)))
1733 DWORD i;
1735 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1736 pbEncoded = *(BYTE **)pbEncoded;
1737 *pbEncoded++ = ASN_UNIVERSALSTRING;
1738 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
1739 pbEncoded += lenBytes;
1740 for (i = 0; i < strLen; i++)
1742 *pbEncoded++ = 0;
1743 *pbEncoded++ = 0;
1744 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
1745 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
1749 return ret;
1752 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1753 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1754 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1756 BOOL ret = FALSE;
1758 __TRY
1760 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1762 switch (value->dwValueType)
1764 case CERT_RDN_ANY_TYPE:
1765 case CERT_RDN_ENCODED_BLOB:
1766 case CERT_RDN_OCTET_STRING:
1767 SetLastError(CRYPT_E_NOT_CHAR_STRING);
1768 break;
1769 case CERT_RDN_NUMERIC_STRING:
1770 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
1771 pbEncoded, pcbEncoded);
1772 break;
1773 case CERT_RDN_PRINTABLE_STRING:
1774 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
1775 pbEncoded, pcbEncoded);
1776 break;
1777 case CERT_RDN_TELETEX_STRING:
1778 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
1779 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1780 break;
1781 case CERT_RDN_VIDEOTEX_STRING:
1782 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
1783 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1784 break;
1785 case CERT_RDN_IA5_STRING:
1786 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
1787 pbEncoded, pcbEncoded);
1788 break;
1789 case CERT_RDN_GRAPHIC_STRING:
1790 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
1791 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1792 break;
1793 case CERT_RDN_VISIBLE_STRING:
1794 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
1795 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1796 break;
1797 case CERT_RDN_GENERAL_STRING:
1798 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
1799 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1800 break;
1801 case CERT_RDN_UNIVERSAL_STRING:
1802 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
1803 pbEncoded, pcbEncoded);
1804 break;
1805 case CERT_RDN_BMP_STRING:
1806 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1807 pbEncoded, pcbEncoded);
1808 break;
1809 case CERT_RDN_UTF8_STRING:
1810 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1811 pbEncoded, pcbEncoded);
1812 break;
1813 default:
1814 SetLastError(CRYPT_E_ASN1_CHOICE);
1817 __EXCEPT_PAGE_FAULT
1819 SetLastError(STATUS_ACCESS_VIOLATION);
1821 __ENDTRY
1822 return ret;
1825 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
1826 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1827 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1829 BOOL ret;
1831 __TRY
1833 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1834 DWORD bytesNeeded = 0, lenBytes, size, i;
1836 TRACE("encoding name with %d RDNs\n", info->cRDN);
1837 ret = TRUE;
1838 for (i = 0; ret && i < info->cRDN; i++)
1840 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1841 CRYPT_AsnEncodeNameValue, NULL, &size);
1842 if (ret)
1843 bytesNeeded += size;
1845 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1846 bytesNeeded += 1 + lenBytes;
1847 if (ret)
1849 if (!pbEncoded)
1850 *pcbEncoded = bytesNeeded;
1851 else
1853 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1854 pbEncoded, pcbEncoded, bytesNeeded)))
1856 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1857 pbEncoded = *(BYTE **)pbEncoded;
1858 *pbEncoded++ = ASN_SEQUENCEOF;
1859 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1860 &lenBytes);
1861 pbEncoded += lenBytes;
1862 for (i = 0; ret && i < info->cRDN; i++)
1864 size = bytesNeeded;
1865 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1866 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, pbEncoded,
1867 &size);
1868 if (ret)
1870 pbEncoded += size;
1871 bytesNeeded -= size;
1878 __EXCEPT_PAGE_FAULT
1880 SetLastError(STATUS_ACCESS_VIOLATION);
1881 ret = FALSE;
1883 __ENDTRY
1884 return ret;
1887 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1888 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1889 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1891 BOOL val = *(const BOOL *)pvStructInfo, ret;
1893 TRACE("%d\n", val);
1895 if (!pbEncoded)
1897 *pcbEncoded = 3;
1898 ret = TRUE;
1900 else if (*pcbEncoded < 3)
1902 *pcbEncoded = 3;
1903 SetLastError(ERROR_MORE_DATA);
1904 ret = FALSE;
1906 else
1908 *pcbEncoded = 3;
1909 *pbEncoded++ = ASN_BOOL;
1910 *pbEncoded++ = 1;
1911 *pbEncoded++ = val ? 0xff : 0;
1912 ret = TRUE;
1914 TRACE("returning %d (%08x)\n", ret, GetLastError());
1915 return ret;
1918 static BOOL WINAPI CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType,
1919 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1920 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1922 const CERT_ALT_NAME_ENTRY *entry =
1923 (const CERT_ALT_NAME_ENTRY *)pvStructInfo;
1924 BOOL ret;
1925 DWORD dataLen;
1926 BYTE tag;
1928 ret = TRUE;
1929 switch (entry->dwAltNameChoice)
1931 case CERT_ALT_NAME_RFC822_NAME:
1932 case CERT_ALT_NAME_DNS_NAME:
1933 case CERT_ALT_NAME_URL:
1934 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1935 if (entry->u.pwszURL)
1937 DWORD i;
1939 /* Not + 1: don't encode the NULL-terminator */
1940 dataLen = lstrlenW(entry->u.pwszURL);
1941 for (i = 0; ret && i < dataLen; i++)
1943 if (entry->u.pwszURL[i] > 0x7f)
1945 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1946 ret = FALSE;
1947 *pcbEncoded = i;
1951 else
1952 dataLen = 0;
1953 break;
1954 case CERT_ALT_NAME_DIRECTORY_NAME:
1955 tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1);
1956 dataLen = entry->u.DirectoryName.cbData;
1957 break;
1958 case CERT_ALT_NAME_IP_ADDRESS:
1959 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1960 dataLen = entry->u.IPAddress.cbData;
1961 break;
1962 case CERT_ALT_NAME_REGISTERED_ID:
1964 struct AsnEncodeTagSwappedItem swapped =
1965 { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID,
1966 CRYPT_AsnEncodeOid };
1968 return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded,
1969 pcbEncoded);
1971 case CERT_ALT_NAME_OTHER_NAME:
1972 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
1973 return FALSE;
1974 default:
1975 SetLastError(E_INVALIDARG);
1976 return FALSE;
1978 if (ret)
1980 DWORD bytesNeeded, lenBytes;
1982 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1983 bytesNeeded = 1 + dataLen + lenBytes;
1984 if (!pbEncoded)
1985 *pcbEncoded = bytesNeeded;
1986 else if (*pcbEncoded < bytesNeeded)
1988 SetLastError(ERROR_MORE_DATA);
1989 *pcbEncoded = bytesNeeded;
1990 ret = FALSE;
1992 else
1994 *pbEncoded++ = tag;
1995 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1996 pbEncoded += lenBytes;
1997 switch (entry->dwAltNameChoice)
1999 case CERT_ALT_NAME_RFC822_NAME:
2000 case CERT_ALT_NAME_DNS_NAME:
2001 case CERT_ALT_NAME_URL:
2003 DWORD i;
2005 for (i = 0; i < dataLen; i++)
2006 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
2007 break;
2009 case CERT_ALT_NAME_DIRECTORY_NAME:
2010 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen);
2011 break;
2012 case CERT_ALT_NAME_IP_ADDRESS:
2013 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
2014 break;
2016 if (ret)
2017 *pcbEncoded = bytesNeeded;
2020 TRACE("returning %d (%08x)\n", ret, GetLastError());
2021 return ret;
2024 static BOOL WINAPI CRYPT_AsnEncodeIntegerSwapBytes(DWORD dwCertEncodingType,
2025 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2026 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2028 BOOL ret;
2030 __TRY
2032 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2033 CRYPT_DATA_BLOB newBlob = { blob->cbData, NULL };
2035 ret = TRUE;
2036 if (newBlob.cbData)
2038 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2039 if (newBlob.pbData)
2041 DWORD i;
2043 for (i = 0; i < newBlob.cbData; i++)
2044 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2046 else
2047 ret = FALSE;
2049 if (ret)
2050 ret = CRYPT_AsnEncodeInteger(dwCertEncodingType, lpszStructType,
2051 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2052 CryptMemFree(newBlob.pbData);
2054 __EXCEPT_PAGE_FAULT
2056 SetLastError(STATUS_ACCESS_VIOLATION);
2057 ret = FALSE;
2059 __ENDTRY
2060 return ret;
2063 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
2064 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2065 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2067 BOOL ret;
2069 __TRY
2071 const CERT_AUTHORITY_KEY_ID_INFO *info =
2072 (const CERT_AUTHORITY_KEY_ID_INFO *)pvStructInfo;
2073 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2074 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2075 struct AsnConstructedItem constructed = { 0 };
2076 DWORD cItem = 0, cSwapped = 0;
2078 if (info->KeyId.cbData)
2080 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2081 swapped[cSwapped].pvStructInfo = &info->KeyId;
2082 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2083 items[cItem].pvStructInfo = &swapped[cSwapped];
2084 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2085 cSwapped++;
2086 cItem++;
2088 if (info->CertIssuer.cbData)
2090 constructed.tag = 1;
2091 constructed.pvStructInfo = &info->CertIssuer;
2092 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2093 items[cItem].pvStructInfo = &constructed;
2094 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2095 cItem++;
2097 if (info->CertSerialNumber.cbData)
2099 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2100 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2101 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2102 items[cItem].pvStructInfo = &swapped[cSwapped];
2103 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2104 cSwapped++;
2105 cItem++;
2107 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2108 pEncodePara, pbEncoded, pcbEncoded);
2110 __EXCEPT_PAGE_FAULT
2112 SetLastError(STATUS_ACCESS_VIOLATION);
2113 ret = FALSE;
2115 __ENDTRY
2116 return ret;
2119 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2120 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2121 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2123 BOOL ret;
2125 __TRY
2127 const CERT_ALT_NAME_INFO *info =
2128 (const CERT_ALT_NAME_INFO *)pvStructInfo;
2129 DWORD bytesNeeded, dataLen, lenBytes, i;
2131 ret = TRUE;
2132 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2133 * can't encode an erroneous entry index if it's bigger than this.
2135 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2137 DWORD len;
2139 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, NULL,
2140 &info->rgAltEntry[i], 0, NULL, NULL, &len);
2141 if (ret)
2142 dataLen += len;
2143 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2145 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2146 * the bad character, now set the index of the bad
2147 * entry
2149 *pcbEncoded = (BYTE)i <<
2150 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2153 if (ret)
2155 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2156 bytesNeeded = 1 + lenBytes + dataLen;
2157 if (!pbEncoded)
2159 *pcbEncoded = bytesNeeded;
2160 ret = TRUE;
2162 else
2164 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2165 pbEncoded, pcbEncoded, bytesNeeded)))
2167 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2168 pbEncoded = *(BYTE **)pbEncoded;
2169 *pbEncoded++ = ASN_SEQUENCEOF;
2170 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2171 pbEncoded += lenBytes;
2172 for (i = 0; ret && i < info->cAltEntry; i++)
2174 DWORD len = dataLen;
2176 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType,
2177 NULL, &info->rgAltEntry[i], 0, NULL, pbEncoded, &len);
2178 if (ret)
2180 pbEncoded += len;
2181 dataLen -= len;
2188 __EXCEPT_PAGE_FAULT
2190 SetLastError(STATUS_ACCESS_VIOLATION);
2191 ret = FALSE;
2193 __ENDTRY
2194 return ret;
2197 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2198 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2199 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2201 BOOL ret;
2203 __TRY
2205 const CERT_AUTHORITY_KEY_ID2_INFO *info =
2206 (const CERT_AUTHORITY_KEY_ID2_INFO *)pvStructInfo;
2207 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2208 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2209 DWORD cItem = 0, cSwapped = 0;
2211 if (info->KeyId.cbData)
2213 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2214 swapped[cSwapped].pvStructInfo = &info->KeyId;
2215 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2216 items[cItem].pvStructInfo = &swapped[cSwapped];
2217 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2218 cSwapped++;
2219 cItem++;
2221 if (info->AuthorityCertIssuer.cAltEntry)
2223 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2224 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2225 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2226 items[cItem].pvStructInfo = &swapped[cSwapped];
2227 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2228 cSwapped++;
2229 cItem++;
2231 if (info->AuthorityCertSerialNumber.cbData)
2233 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2234 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2235 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2236 items[cItem].pvStructInfo = &swapped[cSwapped];
2237 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2238 cSwapped++;
2239 cItem++;
2241 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2242 pEncodePara, pbEncoded, pcbEncoded);
2244 __EXCEPT_PAGE_FAULT
2246 SetLastError(STATUS_ACCESS_VIOLATION);
2247 ret = FALSE;
2249 __ENDTRY
2250 return ret;
2253 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2254 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2255 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2257 BOOL ret;
2259 __TRY
2261 const CERT_BASIC_CONSTRAINTS_INFO *info =
2262 (const CERT_BASIC_CONSTRAINTS_INFO *)pvStructInfo;
2263 struct AsnEncodeSequenceItem items[3] = {
2264 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2265 { 0 }
2267 DWORD cItem = 1;
2269 if (info->fPathLenConstraint)
2271 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2272 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2273 cItem++;
2275 if (info->cSubtreesConstraint)
2277 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2278 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2279 cItem++;
2281 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2282 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2284 __EXCEPT_PAGE_FAULT
2286 SetLastError(STATUS_ACCESS_VIOLATION);
2287 ret = FALSE;
2289 __ENDTRY
2290 return ret;
2293 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2294 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2295 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2297 BOOL ret;
2299 __TRY
2301 const CERT_BASIC_CONSTRAINTS2_INFO *info =
2302 (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
2303 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2304 DWORD cItem = 0;
2306 if (info->fCA)
2308 items[cItem].pvStructInfo = &info->fCA;
2309 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2310 cItem++;
2312 if (info->fPathLenConstraint)
2314 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2315 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2316 cItem++;
2318 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2319 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2321 __EXCEPT_PAGE_FAULT
2323 SetLastError(STATUS_ACCESS_VIOLATION);
2324 ret = FALSE;
2326 __ENDTRY
2327 return ret;
2330 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
2331 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2332 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2334 BOOL ret;
2336 __TRY
2338 const BLOBHEADER *hdr =
2339 (const BLOBHEADER *)pvStructInfo;
2341 if (hdr->bType != PUBLICKEYBLOB)
2343 SetLastError(E_INVALIDARG);
2344 ret = FALSE;
2346 else
2348 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
2349 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
2350 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
2351 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
2352 struct AsnEncodeSequenceItem items[] = {
2353 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
2354 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
2357 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2358 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
2359 pcbEncoded);
2362 __EXCEPT_PAGE_FAULT
2364 SetLastError(STATUS_ACCESS_VIOLATION);
2365 ret = FALSE;
2367 __ENDTRY
2368 return ret;
2371 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
2372 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2373 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2375 BOOL ret;
2377 __TRY
2379 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2380 DWORD bytesNeeded, lenBytes;
2382 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
2383 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
2385 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
2386 bytesNeeded = 1 + lenBytes + blob->cbData;
2387 if (!pbEncoded)
2389 *pcbEncoded = bytesNeeded;
2390 ret = TRUE;
2392 else
2394 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2395 pcbEncoded, bytesNeeded)))
2397 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2398 pbEncoded = *(BYTE **)pbEncoded;
2399 *pbEncoded++ = ASN_OCTETSTRING;
2400 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
2401 pbEncoded += lenBytes;
2402 if (blob->cbData)
2403 memcpy(pbEncoded, blob->pbData, blob->cbData);
2407 __EXCEPT_PAGE_FAULT
2409 SetLastError(STATUS_ACCESS_VIOLATION);
2410 ret = FALSE;
2412 __ENDTRY
2413 TRACE("returning %d (%08x)\n", ret, GetLastError());
2414 return ret;
2417 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
2418 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2419 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2421 BOOL ret;
2423 __TRY
2425 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2426 DWORD bytesNeeded, lenBytes, dataBytes;
2427 BYTE unusedBits;
2429 /* yep, MS allows cUnusedBits to be >= 8 */
2430 if (!blob->cUnusedBits)
2432 dataBytes = blob->cbData;
2433 unusedBits = 0;
2435 else if (blob->cbData * 8 > blob->cUnusedBits)
2437 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
2438 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
2439 blob->cUnusedBits;
2441 else
2443 dataBytes = 0;
2444 unusedBits = 0;
2446 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
2447 bytesNeeded = 1 + lenBytes + dataBytes + 1;
2448 if (!pbEncoded)
2450 *pcbEncoded = bytesNeeded;
2451 ret = TRUE;
2453 else
2455 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2456 pcbEncoded, bytesNeeded)))
2458 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2459 pbEncoded = *(BYTE **)pbEncoded;
2460 *pbEncoded++ = ASN_BITSTRING;
2461 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
2462 pbEncoded += lenBytes;
2463 *pbEncoded++ = unusedBits;
2464 if (dataBytes)
2466 BYTE mask = 0xff << unusedBits;
2468 if (dataBytes > 1)
2470 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
2471 pbEncoded += dataBytes - 1;
2473 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
2478 __EXCEPT_PAGE_FAULT
2480 SetLastError(STATUS_ACCESS_VIOLATION);
2481 ret = FALSE;
2483 __ENDTRY
2484 return ret;
2487 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
2488 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2489 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2491 BOOL ret;
2493 __TRY
2495 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2496 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
2498 ret = TRUE;
2499 if (newBlob.cbData)
2501 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2502 if (newBlob.pbData)
2504 DWORD i;
2506 for (i = 0; i < newBlob.cbData; i++)
2507 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2509 else
2510 ret = FALSE;
2512 if (ret)
2513 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
2514 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2515 CryptMemFree(newBlob.pbData);
2517 __EXCEPT_PAGE_FAULT
2519 SetLastError(STATUS_ACCESS_VIOLATION);
2520 ret = FALSE;
2522 __ENDTRY
2523 return ret;
2526 BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
2527 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2528 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2530 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
2532 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
2533 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2536 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
2537 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2538 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2540 BOOL ret;
2542 __TRY
2544 DWORD significantBytes, lenBytes;
2545 BYTE padByte = 0, bytesNeeded;
2546 BOOL pad = FALSE;
2547 const CRYPT_INTEGER_BLOB *blob =
2548 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2550 significantBytes = blob->cbData;
2551 if (significantBytes)
2553 if (blob->pbData[significantBytes - 1] & 0x80)
2555 /* negative, lop off leading (little-endian) 0xffs */
2556 for (; significantBytes > 0 &&
2557 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
2559 if (blob->pbData[significantBytes - 1] < 0x80)
2561 padByte = 0xff;
2562 pad = TRUE;
2565 else
2567 /* positive, lop off leading (little-endian) zeroes */
2568 for (; significantBytes > 0 &&
2569 !blob->pbData[significantBytes - 1]; significantBytes--)
2571 if (significantBytes == 0)
2572 significantBytes = 1;
2573 if (blob->pbData[significantBytes - 1] > 0x7f)
2575 padByte = 0;
2576 pad = TRUE;
2580 if (pad)
2581 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2582 else
2583 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2584 bytesNeeded = 1 + lenBytes + significantBytes;
2585 if (pad)
2586 bytesNeeded++;
2587 if (!pbEncoded)
2589 *pcbEncoded = bytesNeeded;
2590 ret = TRUE;
2592 else
2594 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2595 pcbEncoded, bytesNeeded)))
2597 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2598 pbEncoded = *(BYTE **)pbEncoded;
2599 *pbEncoded++ = ASN_INTEGER;
2600 if (pad)
2602 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2603 pbEncoded += lenBytes;
2604 *pbEncoded++ = padByte;
2606 else
2608 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2609 pbEncoded += lenBytes;
2611 for (; significantBytes > 0; significantBytes--)
2612 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2616 __EXCEPT_PAGE_FAULT
2618 SetLastError(STATUS_ACCESS_VIOLATION);
2619 ret = FALSE;
2621 __ENDTRY
2622 return ret;
2625 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
2626 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2627 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2629 BOOL ret;
2631 __TRY
2633 DWORD significantBytes, lenBytes;
2634 BYTE bytesNeeded;
2635 BOOL pad = FALSE;
2636 const CRYPT_INTEGER_BLOB *blob =
2637 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2639 significantBytes = blob->cbData;
2640 if (significantBytes)
2642 /* positive, lop off leading (little-endian) zeroes */
2643 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
2644 significantBytes--)
2646 if (significantBytes == 0)
2647 significantBytes = 1;
2648 if (blob->pbData[significantBytes - 1] > 0x7f)
2649 pad = TRUE;
2651 if (pad)
2652 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2653 else
2654 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2655 bytesNeeded = 1 + lenBytes + significantBytes;
2656 if (pad)
2657 bytesNeeded++;
2658 if (!pbEncoded)
2660 *pcbEncoded = bytesNeeded;
2661 ret = TRUE;
2663 else
2665 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2666 pcbEncoded, bytesNeeded)))
2668 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2669 pbEncoded = *(BYTE **)pbEncoded;
2670 *pbEncoded++ = ASN_INTEGER;
2671 if (pad)
2673 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2674 pbEncoded += lenBytes;
2675 *pbEncoded++ = 0;
2677 else
2679 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2680 pbEncoded += lenBytes;
2682 for (; significantBytes > 0; significantBytes--)
2683 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2687 __EXCEPT_PAGE_FAULT
2689 SetLastError(STATUS_ACCESS_VIOLATION);
2690 ret = FALSE;
2692 __ENDTRY
2693 return ret;
2696 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
2697 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2698 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2700 CRYPT_INTEGER_BLOB blob;
2701 BOOL ret;
2703 /* Encode as an unsigned integer, then change the tag to enumerated */
2704 blob.cbData = sizeof(DWORD);
2705 blob.pbData = (BYTE *)pvStructInfo;
2706 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
2707 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2708 if (ret && pbEncoded)
2710 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2711 pbEncoded = *(BYTE **)pbEncoded;
2712 pbEncoded[0] = ASN_ENUMERATED;
2714 return ret;
2717 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
2718 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2719 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2721 BOOL ret;
2723 __TRY
2725 SYSTEMTIME sysTime;
2726 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2727 * temporary buffer because the output buffer is not NULL-terminated.
2729 char buf[16];
2730 static const DWORD bytesNeeded = sizeof(buf) - 1;
2732 if (!pbEncoded)
2734 *pcbEncoded = bytesNeeded;
2735 ret = TRUE;
2737 else
2739 /* Sanity check the year, this is a two-digit year format */
2740 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2741 &sysTime);
2742 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
2744 SetLastError(CRYPT_E_BAD_ENCODE);
2745 ret = FALSE;
2747 if (ret)
2749 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2750 pbEncoded, pcbEncoded, bytesNeeded)))
2752 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2753 pbEncoded = *(BYTE **)pbEncoded;
2754 buf[0] = ASN_UTCTIME;
2755 buf[1] = bytesNeeded - 2;
2756 snprintf(buf + 2, sizeof(buf) - 2,
2757 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
2758 sysTime.wYear - 2000 : sysTime.wYear - 1900,
2759 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2760 sysTime.wMinute, sysTime.wSecond);
2761 memcpy(pbEncoded, buf, bytesNeeded);
2766 __EXCEPT_PAGE_FAULT
2768 SetLastError(STATUS_ACCESS_VIOLATION);
2769 ret = FALSE;
2771 __ENDTRY
2772 return ret;
2775 static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
2776 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2777 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2779 BOOL ret;
2781 __TRY
2783 SYSTEMTIME sysTime;
2784 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2785 * temporary buffer because the output buffer is not NULL-terminated.
2787 char buf[18];
2788 static const DWORD bytesNeeded = sizeof(buf) - 1;
2790 if (!pbEncoded)
2792 *pcbEncoded = bytesNeeded;
2793 ret = TRUE;
2795 else
2797 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2798 &sysTime);
2799 if (ret)
2800 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2801 pcbEncoded, bytesNeeded);
2802 if (ret)
2804 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2805 pbEncoded = *(BYTE **)pbEncoded;
2806 buf[0] = ASN_GENERALTIME;
2807 buf[1] = bytesNeeded - 2;
2808 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
2809 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2810 sysTime.wMinute, sysTime.wSecond);
2811 memcpy(pbEncoded, buf, bytesNeeded);
2815 __EXCEPT_PAGE_FAULT
2817 SetLastError(STATUS_ACCESS_VIOLATION);
2818 ret = FALSE;
2820 __ENDTRY
2821 return ret;
2824 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
2825 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2826 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2828 BOOL ret;
2830 __TRY
2832 SYSTEMTIME sysTime;
2834 /* Check the year, if it's in the UTCTime range call that encode func */
2835 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
2836 return FALSE;
2837 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
2838 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
2839 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2840 else
2841 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
2842 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
2843 pcbEncoded);
2845 __EXCEPT_PAGE_FAULT
2847 SetLastError(STATUS_ACCESS_VIOLATION);
2848 ret = FALSE;
2850 __ENDTRY
2851 return ret;
2854 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
2855 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2856 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2858 BOOL ret;
2860 __TRY
2862 DWORD bytesNeeded, dataLen, lenBytes, i;
2863 const CRYPT_SEQUENCE_OF_ANY *seq =
2864 (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2866 for (i = 0, dataLen = 0; i < seq->cValue; i++)
2867 dataLen += seq->rgValue[i].cbData;
2868 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2869 bytesNeeded = 1 + lenBytes + dataLen;
2870 if (!pbEncoded)
2872 *pcbEncoded = bytesNeeded;
2873 ret = TRUE;
2875 else
2877 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2878 pcbEncoded, bytesNeeded)))
2880 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2881 pbEncoded = *(BYTE **)pbEncoded;
2882 *pbEncoded++ = ASN_SEQUENCEOF;
2883 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2884 pbEncoded += lenBytes;
2885 for (i = 0; i < seq->cValue; i++)
2887 memcpy(pbEncoded, seq->rgValue[i].pbData,
2888 seq->rgValue[i].cbData);
2889 pbEncoded += seq->rgValue[i].cbData;
2894 __EXCEPT_PAGE_FAULT
2896 SetLastError(STATUS_ACCESS_VIOLATION);
2897 ret = FALSE;
2899 __ENDTRY
2900 return ret;
2903 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
2904 BYTE *pbEncoded, DWORD *pcbEncoded)
2906 BOOL ret = TRUE;
2907 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2908 struct AsnConstructedItem constructed = { 0 };
2909 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2910 DWORD cItem = 0, cSwapped = 0;
2912 switch (distPoint->DistPointName.dwDistPointNameChoice)
2914 case CRL_DIST_POINT_NO_NAME:
2915 /* do nothing */
2916 break;
2917 case CRL_DIST_POINT_FULL_NAME:
2918 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
2919 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
2920 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2921 constructed.tag = 0;
2922 constructed.pvStructInfo = &swapped[cSwapped];
2923 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
2924 items[cItem].pvStructInfo = &constructed;
2925 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2926 cSwapped++;
2927 cItem++;
2928 break;
2929 case CRL_DIST_POINT_ISSUER_RDN_NAME:
2930 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2931 ret = FALSE;
2932 break;
2933 default:
2934 ret = FALSE;
2936 if (ret && distPoint->ReasonFlags.cbData)
2938 swapped[cSwapped].tag = ASN_CONTEXT | 1;
2939 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
2940 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
2941 items[cItem].pvStructInfo = &swapped[cSwapped];
2942 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2943 cSwapped++;
2944 cItem++;
2946 if (ret && distPoint->CRLIssuer.cAltEntry)
2948 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
2949 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
2950 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2951 items[cItem].pvStructInfo = &swapped[cSwapped];
2952 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2953 cSwapped++;
2954 cItem++;
2956 if (ret)
2957 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
2958 pbEncoded, pcbEncoded);
2959 return ret;
2962 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
2963 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2964 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2966 BOOL ret;
2968 __TRY
2970 const CRL_DIST_POINTS_INFO *info =
2971 (const CRL_DIST_POINTS_INFO *)pvStructInfo;
2973 if (!info->cDistPoint)
2975 SetLastError(E_INVALIDARG);
2976 ret = FALSE;
2978 else
2980 DWORD bytesNeeded, dataLen, lenBytes, i;
2982 ret = TRUE;
2983 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
2985 DWORD len;
2987 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
2988 &len);
2989 if (ret)
2990 dataLen += len;
2991 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2993 /* Have to propagate index of failing character */
2994 *pcbEncoded = len;
2997 if (ret)
2999 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3000 bytesNeeded = 1 + lenBytes + dataLen;
3001 if (!pbEncoded)
3003 *pcbEncoded = bytesNeeded;
3004 ret = TRUE;
3006 else
3008 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3009 pbEncoded, pcbEncoded, bytesNeeded)))
3011 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3012 pbEncoded = *(BYTE **)pbEncoded;
3013 *pbEncoded++ = ASN_SEQUENCEOF;
3014 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
3015 pbEncoded += lenBytes;
3016 for (i = 0; ret && i < info->cDistPoint; i++)
3018 DWORD len = dataLen;
3020 ret = CRYPT_AsnEncodeDistPoint(
3021 &info->rgDistPoint[i], pbEncoded, &len);
3022 if (ret)
3024 pbEncoded += len;
3025 dataLen -= len;
3033 __EXCEPT_PAGE_FAULT
3035 SetLastError(STATUS_ACCESS_VIOLATION);
3036 ret = FALSE;
3038 __ENDTRY
3039 return ret;
3042 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3043 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3044 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3046 BOOL ret;
3048 __TRY
3050 const CERT_ENHKEY_USAGE *usage =
3051 (const CERT_ENHKEY_USAGE *)pvStructInfo;
3052 DWORD bytesNeeded = 0, lenBytes, size, i;
3054 ret = TRUE;
3055 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3057 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3058 usage->rgpszUsageIdentifier[i],
3059 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
3060 if (ret)
3061 bytesNeeded += size;
3063 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3064 bytesNeeded += 1 + lenBytes;
3065 if (ret)
3067 if (!pbEncoded)
3068 *pcbEncoded = bytesNeeded;
3069 else
3071 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3072 pbEncoded, pcbEncoded, bytesNeeded)))
3074 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3075 pbEncoded = *(BYTE **)pbEncoded;
3076 *pbEncoded++ = ASN_SEQUENCEOF;
3077 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
3078 &lenBytes);
3079 pbEncoded += lenBytes;
3080 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3082 size = bytesNeeded;
3083 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3084 usage->rgpszUsageIdentifier[i],
3085 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
3086 &size);
3087 if (ret)
3089 pbEncoded += size;
3090 bytesNeeded -= size;
3097 __EXCEPT_PAGE_FAULT
3099 SetLastError(STATUS_ACCESS_VIOLATION);
3100 ret = FALSE;
3102 __ENDTRY
3103 return ret;
3106 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
3107 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3108 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3110 BOOL ret;
3112 __TRY
3114 const CRL_ISSUING_DIST_POINT *point =
3115 (const CRL_ISSUING_DIST_POINT *)pvStructInfo;
3116 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3117 struct AsnConstructedItem constructed = { 0 };
3118 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3119 DWORD cItem = 0, cSwapped = 0;
3121 ret = TRUE;
3122 switch (point->DistPointName.dwDistPointNameChoice)
3124 case CRL_DIST_POINT_NO_NAME:
3125 /* do nothing */
3126 break;
3127 case CRL_DIST_POINT_FULL_NAME:
3128 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3129 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3130 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3131 constructed.tag = 0;
3132 constructed.pvStructInfo = &swapped[cSwapped];
3133 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3134 items[cItem].pvStructInfo = &constructed;
3135 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3136 cSwapped++;
3137 cItem++;
3138 break;
3139 default:
3140 SetLastError(E_INVALIDARG);
3141 ret = FALSE;
3143 if (ret && point->fOnlyContainsUserCerts)
3145 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3146 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3147 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3148 items[cItem].pvStructInfo = &swapped[cSwapped];
3149 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3150 cSwapped++;
3151 cItem++;
3153 if (ret && point->fOnlyContainsCACerts)
3155 swapped[cSwapped].tag = ASN_CONTEXT | 2;
3156 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3157 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3158 items[cItem].pvStructInfo = &swapped[cSwapped];
3159 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3160 cSwapped++;
3161 cItem++;
3163 if (ret && point->OnlySomeReasonFlags.cbData)
3165 swapped[cSwapped].tag = ASN_CONTEXT | 3;
3166 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3167 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3168 items[cItem].pvStructInfo = &swapped[cSwapped];
3169 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3170 cSwapped++;
3171 cItem++;
3173 if (ret && point->fIndirectCRL)
3175 swapped[cSwapped].tag = ASN_CONTEXT | 4;
3176 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
3177 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3178 items[cItem].pvStructInfo = &swapped[cSwapped];
3179 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3180 cSwapped++;
3181 cItem++;
3183 if (ret)
3184 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3185 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3187 __EXCEPT_PAGE_FAULT
3189 SetLastError(STATUS_ACCESS_VIOLATION);
3190 ret = FALSE;
3192 __ENDTRY
3193 return ret;
3196 static BOOL WINAPI CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType,
3197 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3198 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3200 BOOL ret;
3201 const CERT_GENERAL_SUBTREE *subtree =
3202 (const CERT_GENERAL_SUBTREE *)pvStructInfo;
3203 struct AsnEncodeSequenceItem items[3] = {
3204 { &subtree->Base, CRYPT_AsnEncodeAltNameEntry, 0 },
3205 { 0 }
3207 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3208 DWORD cItem = 1, cSwapped = 0;
3210 if (subtree->dwMinimum)
3212 swapped[cSwapped].tag = ASN_CONTEXT | 0;
3213 swapped[cSwapped].pvStructInfo = &subtree->dwMinimum;
3214 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3215 items[cItem].pvStructInfo = &swapped[cSwapped];
3216 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3217 cSwapped++;
3218 cItem++;
3220 if (subtree->fMaximum)
3222 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3223 swapped[cSwapped].pvStructInfo = &subtree->dwMaximum;
3224 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3225 items[cItem].pvStructInfo = &swapped[cSwapped];
3226 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3227 cSwapped++;
3228 cItem++;
3230 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags,
3231 pEncodePara, pbEncoded, pcbEncoded);
3232 return ret;
3235 static BOOL WINAPI CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType,
3236 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3237 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3239 BOOL ret = FALSE;
3240 CRYPT_BLOB_ARRAY permitted = { 0, NULL }, excluded = { 0, NULL };
3242 TRACE("%p\n", pvStructInfo);
3244 __TRY
3246 const CERT_NAME_CONSTRAINTS_INFO *constraints =
3247 (const CERT_NAME_CONSTRAINTS_INFO *)pvStructInfo;
3248 struct AsnEncodeSequenceItem items[2] = { { 0 } };
3249 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3250 DWORD i, cItem = 0, cSwapped = 0;
3252 ret = TRUE;
3253 if (constraints->cPermittedSubtree)
3255 permitted.rgBlob = CryptMemAlloc(
3256 constraints->cPermittedSubtree * sizeof(CRYPT_DER_BLOB));
3257 if (permitted.rgBlob)
3259 permitted.cBlob = constraints->cPermittedSubtree;
3260 memset(permitted.rgBlob, 0,
3261 permitted.cBlob * sizeof(CRYPT_DER_BLOB));
3262 for (i = 0; ret && i < permitted.cBlob; i++)
3263 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3264 NULL, &constraints->rgPermittedSubtree[i],
3265 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3266 (BYTE *)&permitted.rgBlob[i].pbData,
3267 &permitted.rgBlob[i].cbData);
3268 if (ret)
3270 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3271 swapped[cSwapped].pvStructInfo = &permitted;
3272 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3273 items[cItem].pvStructInfo = &swapped[cSwapped];
3274 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3275 cSwapped++;
3276 cItem++;
3279 else
3280 ret = FALSE;
3282 if (constraints->cExcludedSubtree)
3284 excluded.rgBlob = CryptMemAlloc(
3285 constraints->cExcludedSubtree * sizeof(CRYPT_DER_BLOB));
3286 if (excluded.rgBlob)
3288 excluded.cBlob = constraints->cExcludedSubtree;
3289 memset(excluded.rgBlob, 0,
3290 excluded.cBlob * sizeof(CRYPT_DER_BLOB));
3291 for (i = 0; ret && i < excluded.cBlob; i++)
3292 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3293 NULL, &constraints->rgExcludedSubtree[i],
3294 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3295 (BYTE *)&excluded.rgBlob[i].pbData,
3296 &excluded.rgBlob[i].cbData);
3297 if (ret)
3299 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
3300 swapped[cSwapped].pvStructInfo = &excluded;
3301 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3302 items[cItem].pvStructInfo = &swapped[cSwapped];
3303 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3304 cSwapped++;
3305 cItem++;
3308 else
3309 ret = FALSE;
3311 if (ret)
3312 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3313 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3314 for (i = 0; i < permitted.cBlob; i++)
3315 LocalFree(permitted.rgBlob[i].pbData);
3316 for (i = 0; i < excluded.cBlob; i++)
3317 LocalFree(excluded.rgBlob[i].pbData);
3319 __EXCEPT_PAGE_FAULT
3321 SetLastError(STATUS_ACCESS_VIOLATION);
3323 __ENDTRY
3324 CryptMemFree(permitted.rgBlob);
3325 CryptMemFree(excluded.rgBlob);
3326 TRACE("returning %d\n", ret);
3327 return ret;
3330 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
3331 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3332 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3333 DWORD *pcbEncoded)
3335 BOOL ret;
3336 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3337 (const CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3338 struct AsnEncodeSequenceItem items[] = {
3339 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
3340 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
3343 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3344 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3345 pcbEncoded);
3346 return ret;
3349 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
3350 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3351 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3353 BOOL ret = FALSE;
3355 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
3357 SetLastError(E_INVALIDARG);
3358 return FALSE;
3361 __TRY
3363 const CMSG_SIGNER_INFO *info = (const CMSG_SIGNER_INFO *)pvStructInfo;
3365 if (!info->Issuer.cbData)
3366 SetLastError(E_INVALIDARG);
3367 else
3369 struct AsnEncodeSequenceItem items[7] = {
3370 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
3371 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
3372 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
3373 0 },
3375 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3376 DWORD cItem = 3, cSwapped = 0;
3378 if (info->AuthAttrs.cAttr)
3380 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3381 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
3382 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3383 items[cItem].pvStructInfo = &swapped[cSwapped];
3384 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3385 cSwapped++;
3386 cItem++;
3388 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
3389 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
3390 cItem++;
3391 items[cItem].pvStructInfo = &info->EncryptedHash;
3392 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
3393 cItem++;
3394 if (info->UnauthAttrs.cAttr)
3396 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
3397 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
3398 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3399 items[cItem].pvStructInfo = &swapped[cSwapped];
3400 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3401 cSwapped++;
3402 cItem++;
3404 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3405 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3408 __EXCEPT_PAGE_FAULT
3410 SetLastError(STATUS_ACCESS_VIOLATION);
3412 __ENDTRY
3413 return ret;
3416 BOOL CRYPT_AsnEncodePKCSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
3417 DWORD *pcbData)
3419 struct AsnEncodeSequenceItem items[7] = {
3420 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
3422 struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 };
3423 struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 };
3424 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3425 DWORD cItem = 1, cSwapped = 0;
3426 BOOL ret = TRUE;
3428 if (signedInfo->cSignerInfo)
3430 digestAlgorithmsSet.cItems = signedInfo->cSignerInfo;
3431 digestAlgorithmsSet.items = signedInfo->rgSignerInfo;
3432 digestAlgorithmsSet.itemSize = sizeof(CMSG_SIGNER_INFO);
3433 digestAlgorithmsSet.itemOffset =
3434 offsetof(CMSG_SIGNER_INFO, HashAlgorithm);
3435 digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
3436 items[cItem].pvStructInfo = &digestAlgorithmsSet;
3437 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3438 cItem++;
3440 items[cItem].pvStructInfo = &signedInfo->content;
3441 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal;
3442 cItem++;
3443 if (signedInfo->cCertEncoded)
3445 certSet.cItems = signedInfo->cCertEncoded;
3446 certSet.items = signedInfo->rgCertEncoded;
3447 certSet.itemSize = sizeof(CERT_BLOB);
3448 certSet.itemOffset = 0;
3449 certSet.encode = CRYPT_CopyEncodedBlob;
3450 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0;
3451 swapped[cSwapped].pvStructInfo = &certSet;
3452 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3453 items[cItem].pvStructInfo = &swapped[cSwapped];
3454 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3455 cSwapped++;
3456 cItem++;
3458 if (signedInfo->cCrlEncoded)
3460 crlSet.cItems = signedInfo->cCrlEncoded;
3461 crlSet.items = signedInfo->rgCrlEncoded;
3462 crlSet.itemSize = sizeof(CRL_BLOB);
3463 crlSet.itemOffset = 0;
3464 crlSet.encode = CRYPT_CopyEncodedBlob;
3465 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
3466 swapped[cSwapped].pvStructInfo = &crlSet;
3467 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3468 items[cItem].pvStructInfo = &swapped[cSwapped];
3469 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3470 cSwapped++;
3471 cItem++;
3473 if (ret && signedInfo->cSignerInfo)
3475 signerSet.cItems = signedInfo->cSignerInfo;
3476 signerSet.items = signedInfo->rgSignerInfo;
3477 signerSet.itemSize = sizeof(CMSG_SIGNER_INFO);
3478 signerSet.itemOffset = 0;
3479 signerSet.encode = CRYPT_AsnEncodePKCSSignerInfo;
3480 items[cItem].pvStructInfo = &signerSet;
3481 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3482 cItem++;
3484 if (ret)
3485 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
3486 items, cItem, 0, NULL, pvData, pcbData);
3488 return ret;
3491 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
3492 LPCSTR lpszStructType)
3494 CryptEncodeObjectExFunc encodeFunc = NULL;
3496 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3497 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3499 SetLastError(ERROR_FILE_NOT_FOUND);
3500 return NULL;
3503 if (!HIWORD(lpszStructType))
3505 switch (LOWORD(lpszStructType))
3507 case LOWORD(X509_CERT):
3508 encodeFunc = CRYPT_AsnEncodeCert;
3509 break;
3510 case LOWORD(X509_CERT_TO_BE_SIGNED):
3511 encodeFunc = CRYPT_AsnEncodeCertInfo;
3512 break;
3513 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
3514 encodeFunc = CRYPT_AsnEncodeCRLInfo;
3515 break;
3516 case LOWORD(X509_EXTENSIONS):
3517 encodeFunc = CRYPT_AsnEncodeExtensions;
3518 break;
3519 case LOWORD(X509_NAME_VALUE):
3520 encodeFunc = CRYPT_AsnEncodeNameValue;
3521 break;
3522 case LOWORD(X509_NAME):
3523 encodeFunc = CRYPT_AsnEncodeName;
3524 break;
3525 case LOWORD(X509_PUBLIC_KEY_INFO):
3526 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
3527 break;
3528 case LOWORD(X509_AUTHORITY_KEY_ID):
3529 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3530 break;
3531 case LOWORD(X509_ALTERNATE_NAME):
3532 encodeFunc = CRYPT_AsnEncodeAltName;
3533 break;
3534 case LOWORD(X509_BASIC_CONSTRAINTS):
3535 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3536 break;
3537 case LOWORD(X509_BASIC_CONSTRAINTS2):
3538 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3539 break;
3540 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
3541 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
3542 break;
3543 case LOWORD(X509_UNICODE_NAME):
3544 encodeFunc = CRYPT_AsnEncodeUnicodeName;
3545 break;
3546 case LOWORD(PKCS_CONTENT_INFO):
3547 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
3548 break;
3549 case LOWORD(PKCS_ATTRIBUTE):
3550 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
3551 break;
3552 case LOWORD(X509_UNICODE_NAME_VALUE):
3553 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
3554 break;
3555 case LOWORD(X509_OCTET_STRING):
3556 encodeFunc = CRYPT_AsnEncodeOctets;
3557 break;
3558 case LOWORD(X509_BITS):
3559 case LOWORD(X509_KEY_USAGE):
3560 encodeFunc = CRYPT_AsnEncodeBits;
3561 break;
3562 case LOWORD(X509_INTEGER):
3563 encodeFunc = CRYPT_AsnEncodeInt;
3564 break;
3565 case LOWORD(X509_MULTI_BYTE_INTEGER):
3566 encodeFunc = CRYPT_AsnEncodeInteger;
3567 break;
3568 case LOWORD(X509_MULTI_BYTE_UINT):
3569 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
3570 break;
3571 case LOWORD(X509_ENUMERATED):
3572 encodeFunc = CRYPT_AsnEncodeEnumerated;
3573 break;
3574 case LOWORD(X509_CHOICE_OF_TIME):
3575 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
3576 break;
3577 case LOWORD(X509_AUTHORITY_KEY_ID2):
3578 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3579 break;
3580 case LOWORD(X509_SEQUENCE_OF_ANY):
3581 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
3582 break;
3583 case LOWORD(PKCS_UTC_TIME):
3584 encodeFunc = CRYPT_AsnEncodeUtcTime;
3585 break;
3586 case LOWORD(X509_CRL_DIST_POINTS):
3587 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3588 break;
3589 case LOWORD(X509_ENHANCED_KEY_USAGE):
3590 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3591 break;
3592 case LOWORD(PKCS_ATTRIBUTES):
3593 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3594 break;
3595 case LOWORD(X509_ISSUING_DIST_POINT):
3596 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3597 break;
3598 case LOWORD(X509_NAME_CONSTRAINTS):
3599 encodeFunc = CRYPT_AsnEncodeNameConstraints;
3600 break;
3601 case LOWORD(PKCS7_SIGNER_INFO):
3602 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
3603 break;
3606 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3607 encodeFunc = CRYPT_AsnEncodeExtensions;
3608 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3609 encodeFunc = CRYPT_AsnEncodeUtcTime;
3610 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
3611 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3612 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
3613 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3614 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3615 encodeFunc = CRYPT_AsnEncodeEnumerated;
3616 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3617 encodeFunc = CRYPT_AsnEncodeBits;
3618 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3619 encodeFunc = CRYPT_AsnEncodeOctets;
3620 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3621 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3622 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3623 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3624 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3625 encodeFunc = CRYPT_AsnEncodeAltName;
3626 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3627 encodeFunc = CRYPT_AsnEncodeAltName;
3628 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3629 encodeFunc = CRYPT_AsnEncodeAltName;
3630 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3631 encodeFunc = CRYPT_AsnEncodeAltName;
3632 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3633 encodeFunc = CRYPT_AsnEncodeAltName;
3634 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3635 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3636 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3637 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3638 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3639 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3640 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
3641 encodeFunc = CRYPT_AsnEncodeNameConstraints;
3642 return encodeFunc;
3645 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType,
3646 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
3648 static HCRYPTOIDFUNCSET set = NULL;
3649 CryptEncodeObjectFunc encodeFunc = NULL;
3651 if (!set)
3652 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
3653 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3654 (void **)&encodeFunc, hFunc);
3655 return encodeFunc;
3658 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType,
3659 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
3661 static HCRYPTOIDFUNCSET set = NULL;
3662 CryptEncodeObjectExFunc encodeFunc = NULL;
3664 if (!set)
3665 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
3666 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3667 (void **)&encodeFunc, hFunc);
3668 return encodeFunc;
3671 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3672 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
3674 BOOL ret = FALSE;
3675 HCRYPTOIDFUNCADDR hFunc = NULL;
3676 CryptEncodeObjectFunc pCryptEncodeObject = NULL;
3677 CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL;
3679 TRACE_(crypt)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
3680 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
3681 pcbEncoded);
3683 if (!pbEncoded && !pcbEncoded)
3685 SetLastError(ERROR_INVALID_PARAMETER);
3686 return FALSE;
3689 if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType,
3690 lpszStructType)))
3692 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
3693 debugstr_a(lpszStructType));
3694 pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType,
3695 lpszStructType, &hFunc);
3696 if (!pCryptEncodeObject)
3697 pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType,
3698 lpszStructType, &hFunc);
3700 if (pCryptEncodeObject)
3701 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3702 pvStructInfo, pbEncoded, pcbEncoded);
3703 else if (pCryptEncodeObjectEx)
3704 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
3705 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
3706 if (hFunc)
3707 CryptFreeOIDFunctionAddress(hFunc, 0);
3708 TRACE_(crypt)("returning %d\n", ret);
3709 return ret;
3712 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3713 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
3714 void *pvEncoded, DWORD *pcbEncoded)
3716 BOOL ret = FALSE;
3717 HCRYPTOIDFUNCADDR hFunc = NULL;
3718 CryptEncodeObjectExFunc encodeFunc = NULL;
3720 TRACE_(crypt)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
3721 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
3722 pvEncoded, pcbEncoded);
3724 if (!pvEncoded && !pcbEncoded)
3726 SetLastError(ERROR_INVALID_PARAMETER);
3727 return FALSE;
3730 SetLastError(NOERROR);
3731 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
3732 *(BYTE **)pvEncoded = NULL;
3733 encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType);
3734 if (!encodeFunc)
3736 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
3737 debugstr_a(lpszStructType));
3738 encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType,
3739 &hFunc);
3741 if (encodeFunc)
3742 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
3743 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
3744 else
3746 CryptEncodeObjectFunc pCryptEncodeObject =
3747 CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
3749 if (pCryptEncodeObject)
3751 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3753 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3754 pvStructInfo, NULL, pcbEncoded);
3755 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3756 pvEncoded, pcbEncoded, *pcbEncoded)))
3757 ret = pCryptEncodeObject(dwCertEncodingType,
3758 lpszStructType, pvStructInfo, *(BYTE **)pvEncoded,
3759 pcbEncoded);
3761 else
3762 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3763 pvStructInfo, pvEncoded, pcbEncoded);
3766 if (hFunc)
3767 CryptFreeOIDFunctionAddress(hFunc, 0);
3768 TRACE_(crypt)("returning %d\n", ret);
3769 return ret;
3772 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
3773 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3775 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
3776 NULL, 0, NULL, pInfo, pcbInfo);
3779 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
3780 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3781 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3783 BOOL ret;
3784 HCRYPTKEY key;
3785 static CHAR oid[] = szOID_RSA_RSA;
3787 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
3788 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
3789 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
3791 if (!pszPublicKeyObjId)
3792 pszPublicKeyObjId = oid;
3793 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
3795 DWORD keySize = 0;
3797 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
3798 if (ret)
3800 LPBYTE pubKey = CryptMemAlloc(keySize);
3802 if (pubKey)
3804 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
3805 &keySize);
3806 if (ret)
3808 DWORD encodedLen = 0;
3810 ret = CryptEncodeObject(dwCertEncodingType,
3811 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
3812 if (ret)
3814 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
3815 strlen(pszPublicKeyObjId) + 1 + encodedLen;
3817 if (!pInfo)
3818 *pcbInfo = sizeNeeded;
3819 else if (*pcbInfo < sizeNeeded)
3821 SetLastError(ERROR_MORE_DATA);
3822 *pcbInfo = sizeNeeded;
3823 ret = FALSE;
3825 else
3827 pInfo->Algorithm.pszObjId = (char *)pInfo +
3828 sizeof(CERT_PUBLIC_KEY_INFO);
3829 lstrcpyA(pInfo->Algorithm.pszObjId,
3830 pszPublicKeyObjId);
3831 pInfo->Algorithm.Parameters.cbData = 0;
3832 pInfo->Algorithm.Parameters.pbData = NULL;
3833 pInfo->PublicKey.pbData =
3834 (BYTE *)pInfo->Algorithm.pszObjId
3835 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
3836 pInfo->PublicKey.cbData = encodedLen;
3837 pInfo->PublicKey.cUnusedBits = 0;
3838 ret = CryptEncodeObject(dwCertEncodingType,
3839 RSA_CSP_PUBLICKEYBLOB, pubKey,
3840 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
3844 CryptMemFree(pubKey);
3846 else
3847 ret = FALSE;
3849 CryptDestroyKey(key);
3851 return ret;
3854 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
3855 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3856 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
3858 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
3859 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
3860 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3862 static HCRYPTOIDFUNCSET set = NULL;
3863 BOOL ret;
3864 ExportPublicKeyInfoExFunc exportFunc = NULL;
3865 HCRYPTOIDFUNCADDR hFunc = NULL;
3867 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
3868 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
3869 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
3871 if (!hCryptProv)
3873 SetLastError(ERROR_INVALID_PARAMETER);
3874 return FALSE;
3877 if (pszPublicKeyObjId)
3879 if (!set)
3880 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
3882 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
3883 0, (void **)&exportFunc, &hFunc);
3885 if (!exportFunc)
3886 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
3887 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
3888 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
3889 if (hFunc)
3890 CryptFreeOIDFunctionAddress(hFunc, 0);
3891 return ret;
3894 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
3895 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
3897 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
3898 0, 0, NULL, phKey);
3901 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3902 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3903 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3905 BOOL ret;
3906 DWORD pubKeySize = 0;
3908 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
3909 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3911 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3912 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
3913 if (ret)
3915 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
3917 if (pubKey)
3919 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3920 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
3921 &pubKeySize);
3922 if (ret)
3923 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
3924 phKey);
3925 CryptMemFree(pubKey);
3927 else
3928 ret = FALSE;
3930 return ret;
3933 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
3934 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3935 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
3937 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3938 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3939 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3941 static HCRYPTOIDFUNCSET set = NULL;
3942 BOOL ret;
3943 ImportPublicKeyInfoExFunc importFunc = NULL;
3944 HCRYPTOIDFUNCADDR hFunc = NULL;
3946 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
3947 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3949 if (!set)
3950 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
3951 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
3952 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
3953 if (!importFunc)
3954 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
3955 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
3956 pvAuxInfo, phKey);
3957 if (hFunc)
3958 CryptFreeOIDFunctionAddress(hFunc, 0);
3959 return ret;