wined3d: Call SetGlTextureDesc() from BindTexture() rather than from PreLoad().
[wine/testsucceed.git] / dlls / crypt32 / encode.c
blob6d5d152147e5431f4074db2d8c7be457973b7e53
1 /*
2 * Copyright 2005-2007 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER encoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface isn't
21 * implemented, so I implement them here.
23 * References:
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
33 #include <assert.h>
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <stdlib.h>
38 #define NONAMELESSUNION
40 #include "windef.h"
41 #include "winbase.h"
42 #include "wincrypt.h"
43 #include "snmp.h"
44 #include "wine/debug.h"
45 #include "wine/exception.h"
46 #include "wine/unicode.h"
47 #include "crypt32_private.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
50 WINE_DECLARE_DEBUG_CHANNEL(crypt);
52 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
53 BYTE *, DWORD *);
55 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
56 * The dwCertEncodingType and lpszStructType are ignored by the built-in
57 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
58 * since it must call functions in external DLLs that follow these signatures.
60 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
61 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
62 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
63 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
64 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
65 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
66 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
67 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
68 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
69 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
70 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
71 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
72 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
73 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
74 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
75 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
76 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
77 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
78 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
79 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
80 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
81 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
82 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
83 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
84 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
85 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
86 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
87 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
88 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
89 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
90 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
91 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
92 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
94 BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
95 BYTE *pbEncoded, DWORD *pcbEncoded, DWORD bytesNeeded)
97 BOOL ret = TRUE;
99 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
101 if (pEncodePara && pEncodePara->pfnAlloc)
102 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
103 else
104 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
105 if (!*(BYTE **)pbEncoded)
106 ret = FALSE;
107 else
108 *pcbEncoded = bytesNeeded;
110 else if (bytesNeeded > *pcbEncoded)
112 *pcbEncoded = bytesNeeded;
113 SetLastError(ERROR_MORE_DATA);
114 ret = FALSE;
116 else
117 *pcbEncoded = bytesNeeded;
118 return ret;
121 BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
123 DWORD bytesNeeded, significantBytes = 0;
125 if (len <= 0x7f)
126 bytesNeeded = 1;
127 else
129 DWORD temp;
131 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
132 temp <<= 8, significantBytes--)
134 bytesNeeded = significantBytes + 1;
136 if (!pbEncoded)
138 *pcbEncoded = bytesNeeded;
139 return TRUE;
141 if (*pcbEncoded < bytesNeeded)
143 SetLastError(ERROR_MORE_DATA);
144 return FALSE;
146 if (len <= 0x7f)
147 *pbEncoded = (BYTE)len;
148 else
150 DWORD i;
152 *pbEncoded++ = significantBytes | 0x80;
153 for (i = 0; i < significantBytes; i++)
155 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
156 len >>= 8;
159 *pcbEncoded = bytesNeeded;
160 return TRUE;
163 BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
164 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
165 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
167 BOOL ret;
168 DWORD i, dataLen = 0;
170 TRACE("%p, %d, %08x, %p, %p, %d\n", items, cItem, dwFlags, pEncodePara,
171 pbEncoded, *pcbEncoded);
172 for (i = 0, ret = TRUE; ret && i < cItem; i++)
174 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
175 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
176 NULL, &items[i].size);
177 /* Some functions propagate their errors through the size */
178 if (!ret)
179 *pcbEncoded = items[i].size;
180 dataLen += items[i].size;
182 if (ret)
184 DWORD lenBytes, bytesNeeded;
186 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
187 bytesNeeded = 1 + lenBytes + dataLen;
188 if (!pbEncoded)
189 *pcbEncoded = bytesNeeded;
190 else
192 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
193 pcbEncoded, bytesNeeded)))
195 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
196 pbEncoded = *(BYTE **)pbEncoded;
197 *pbEncoded++ = ASN_SEQUENCE;
198 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
199 pbEncoded += lenBytes;
200 for (i = 0; ret && i < cItem; i++)
202 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
203 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
204 NULL, pbEncoded, &items[i].size);
205 /* Some functions propagate their errors through the size */
206 if (!ret)
207 *pcbEncoded = items[i].size;
208 pbEncoded += items[i].size;
213 TRACE("returning %d (%08x)\n", ret, GetLastError());
214 return ret;
217 BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
218 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
219 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
221 BOOL ret;
222 const struct AsnConstructedItem *item =
223 (const struct AsnConstructedItem *)pvStructInfo;
224 DWORD len;
226 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
227 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
229 DWORD dataLen, bytesNeeded;
231 CRYPT_EncodeLen(len, NULL, &dataLen);
232 bytesNeeded = 1 + dataLen + len;
233 if (!pbEncoded)
234 *pcbEncoded = bytesNeeded;
235 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
236 pbEncoded, pcbEncoded, bytesNeeded)))
238 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
239 pbEncoded = *(BYTE **)pbEncoded;
240 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
241 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
242 pbEncoded += dataLen;
243 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
244 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
245 pbEncoded, &len);
246 if (!ret)
248 /* Some functions propagate their errors through the size */
249 *pcbEncoded = len;
253 else
255 /* Some functions propagate their errors through the size */
256 *pcbEncoded = len;
258 return ret;
261 struct AsnEncodeTagSwappedItem
263 BYTE tag;
264 const void *pvStructInfo;
265 CryptEncodeObjectExFunc encodeFunc;
268 /* Sort of a wacky hack, it encodes something using the struct
269 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
270 * given in the struct AsnEncodeTagSwappedItem.
272 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
273 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
274 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
276 BOOL ret;
277 const struct AsnEncodeTagSwappedItem *item =
278 (const struct AsnEncodeTagSwappedItem *)pvStructInfo;
280 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
281 item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
282 if (ret && pbEncoded)
283 *pbEncoded = item->tag;
284 return ret;
287 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
288 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
289 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
291 const DWORD *ver = (const DWORD *)pvStructInfo;
292 BOOL ret;
294 /* CERT_V1 is not encoded */
295 if (*ver == CERT_V1)
297 *pcbEncoded = 0;
298 ret = TRUE;
300 else
302 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
304 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
305 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
307 return ret;
310 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
311 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
312 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
314 const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
315 BOOL ret;
317 if (!pbEncoded)
319 *pcbEncoded = blob->cbData;
320 ret = TRUE;
322 else
324 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
325 pcbEncoded, blob->cbData)))
327 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
328 pbEncoded = *(BYTE **)pbEncoded;
329 if (blob->cbData)
330 memcpy(pbEncoded, blob->pbData, blob->cbData);
331 *pcbEncoded = blob->cbData;
332 ret = TRUE;
335 return ret;
338 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
339 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
340 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
342 BOOL ret;
343 /* This has two filetimes in a row, a NotBefore and a NotAfter */
344 const FILETIME *timePtr = (const FILETIME *)pvStructInfo;
345 struct AsnEncodeSequenceItem items[] = {
346 { timePtr++, CRYPT_AsnEncodeChoiceOfTime, 0 },
347 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
350 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
351 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
352 pcbEncoded);
353 return ret;
356 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
357 * if they are empty.
359 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
360 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
361 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
362 DWORD *pcbEncoded)
364 const CRYPT_ALGORITHM_IDENTIFIER *algo =
365 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
366 static const BYTE asn1Null[] = { ASN_NULL, 0 };
367 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
368 (LPBYTE)asn1Null };
369 BOOL ret;
370 struct AsnEncodeSequenceItem items[2] = {
371 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
372 { NULL, CRYPT_CopyEncodedBlob, 0 },
375 if (algo->Parameters.cbData)
376 items[1].pvStructInfo = &algo->Parameters;
377 else
378 items[1].pvStructInfo = &nullBlob;
379 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
380 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
381 pcbEncoded);
382 return ret;
385 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType,
386 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
387 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
389 const CRYPT_ALGORITHM_IDENTIFIER *algo =
390 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
391 BOOL ret;
392 struct AsnEncodeSequenceItem items[] = {
393 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
394 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
397 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
398 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
399 pcbEncoded);
400 return ret;
403 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
404 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
405 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
407 BOOL ret;
409 __TRY
411 const CERT_PUBLIC_KEY_INFO *info =
412 (const CERT_PUBLIC_KEY_INFO *)pvStructInfo;
413 struct AsnEncodeSequenceItem items[] = {
414 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
415 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
418 TRACE("Encoding public key with OID %s\n",
419 debugstr_a(info->Algorithm.pszObjId));
420 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
421 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
422 pcbEncoded);
424 __EXCEPT_PAGE_FAULT
426 SetLastError(STATUS_ACCESS_VIOLATION);
427 ret = FALSE;
429 __ENDTRY
430 return ret;
433 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
434 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
435 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
437 BOOL ret;
439 __TRY
441 const CERT_SIGNED_CONTENT_INFO *info =
442 (const CERT_SIGNED_CONTENT_INFO *)pvStructInfo;
443 struct AsnEncodeSequenceItem items[] = {
444 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
445 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
446 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
449 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
450 items[2].encodeFunc = CRYPT_AsnEncodeBits;
451 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
452 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
453 pcbEncoded);
455 __EXCEPT_PAGE_FAULT
457 SetLastError(STATUS_ACCESS_VIOLATION);
458 ret = FALSE;
460 __ENDTRY
461 return ret;
464 /* Like in Windows, this blithely ignores the validity of the passed-in
465 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
466 * decode properly, see CRYPT_AsnDecodeCertInfo.
468 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
469 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
470 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
472 BOOL ret;
474 __TRY
476 const CERT_INFO *info = (const CERT_INFO *)pvStructInfo;
477 struct AsnEncodeSequenceItem items[10] = {
478 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
479 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
480 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
481 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
482 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
483 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
484 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfo, 0 },
485 { 0 }
487 struct AsnConstructedItem constructed[3] = { { 0 } };
488 DWORD cItem = 7, cConstructed = 0;
490 if (info->IssuerUniqueId.cbData)
492 constructed[cConstructed].tag = 1;
493 constructed[cConstructed].pvStructInfo = &info->IssuerUniqueId;
494 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
495 items[cItem].pvStructInfo = &constructed[cConstructed];
496 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
497 cConstructed++;
498 cItem++;
500 if (info->SubjectUniqueId.cbData)
502 constructed[cConstructed].tag = 2;
503 constructed[cConstructed].pvStructInfo = &info->SubjectUniqueId;
504 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
505 items[cItem].pvStructInfo = &constructed[cConstructed];
506 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
507 cConstructed++;
508 cItem++;
510 if (info->cExtension)
512 constructed[cConstructed].tag = 3;
513 constructed[cConstructed].pvStructInfo = &info->cExtension;
514 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
515 items[cItem].pvStructInfo = &constructed[cConstructed];
516 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
517 cConstructed++;
518 cItem++;
521 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
522 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
524 __EXCEPT_PAGE_FAULT
526 SetLastError(STATUS_ACCESS_VIOLATION);
527 ret = FALSE;
529 __ENDTRY
530 return ret;
533 static BOOL WINAPI CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
534 BYTE *pbEncoded, DWORD *pcbEncoded)
536 struct AsnEncodeSequenceItem items[3] = {
537 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
538 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
539 { 0 }
541 DWORD cItem = 2;
542 BOOL ret;
544 TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded);
546 if (entry->cExtension)
548 items[cItem].pvStructInfo = &entry->cExtension;
549 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
550 cItem++;
553 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
554 pbEncoded, pcbEncoded);
556 TRACE("returning %d (%08x)\n", ret, GetLastError());
557 return ret;
560 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
561 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
562 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
564 DWORD cCRLEntry = *(const DWORD *)pvStructInfo;
565 DWORD bytesNeeded, dataLen, lenBytes, i;
566 const CRL_ENTRY *rgCRLEntry = *(const CRL_ENTRY *const *)
567 ((const BYTE *)pvStructInfo + sizeof(DWORD));
568 BOOL ret = TRUE;
570 for (i = 0, dataLen = 0; ret && i < cCRLEntry; i++)
572 DWORD size;
574 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
575 if (ret)
576 dataLen += size;
578 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
579 bytesNeeded = 1 + lenBytes + dataLen;
580 if (!pbEncoded)
581 *pcbEncoded = bytesNeeded;
582 else
584 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
585 pcbEncoded, bytesNeeded)))
587 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
588 pbEncoded = *(BYTE **)pbEncoded;
589 *pbEncoded++ = ASN_SEQUENCEOF;
590 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
591 pbEncoded += lenBytes;
592 for (i = 0; i < cCRLEntry; i++)
594 DWORD size = dataLen;
596 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], pbEncoded, &size);
597 pbEncoded += size;
598 dataLen -= size;
602 return ret;
605 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
606 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
607 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
609 const DWORD *ver = (const DWORD *)pvStructInfo;
610 BOOL ret;
612 /* CRL_V1 is not encoded */
613 if (*ver == CRL_V1)
615 *pcbEncoded = 0;
616 ret = TRUE;
618 else
619 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
620 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
621 return ret;
624 /* Like in Windows, this blithely ignores the validity of the passed-in
625 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
626 * decode properly, see CRYPT_AsnDecodeCRLInfo.
628 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
629 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
630 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
632 BOOL ret;
634 __TRY
636 const CRL_INFO *info = (const CRL_INFO *)pvStructInfo;
637 struct AsnEncodeSequenceItem items[7] = {
638 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
639 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
640 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
641 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
642 { 0 }
644 struct AsnConstructedItem constructed[1] = { { 0 } };
645 DWORD cItem = 4, cConstructed = 0;
647 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
649 items[cItem].pvStructInfo = &info->NextUpdate;
650 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
651 cItem++;
653 if (info->cCRLEntry)
655 items[cItem].pvStructInfo = &info->cCRLEntry;
656 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
657 cItem++;
659 if (info->cExtension)
661 constructed[cConstructed].tag = 0;
662 constructed[cConstructed].pvStructInfo = &info->cExtension;
663 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
664 items[cItem].pvStructInfo = &constructed[cConstructed];
665 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
666 cConstructed++;
667 cItem++;
670 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
671 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
673 __EXCEPT_PAGE_FAULT
675 SetLastError(STATUS_ACCESS_VIOLATION);
676 ret = FALSE;
678 __ENDTRY
679 return ret;
682 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
683 DWORD *pcbEncoded)
685 BOOL ret;
686 struct AsnEncodeSequenceItem items[3] = {
687 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
688 { NULL, NULL, 0 },
689 { NULL, NULL, 0 },
691 DWORD cItem = 1;
693 TRACE("%p, %p, %d\n", ext, pbEncoded, *pcbEncoded);
695 if (ext->fCritical)
697 items[cItem].pvStructInfo = &ext->fCritical;
698 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
699 cItem++;
701 items[cItem].pvStructInfo = &ext->Value;
702 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
703 cItem++;
705 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
706 pbEncoded, pcbEncoded);
707 TRACE("returning %d (%08x)\n", ret, GetLastError());
708 return ret;
711 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
712 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
713 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
715 BOOL ret;
717 __TRY
719 DWORD bytesNeeded, dataLen, lenBytes, i;
720 const CERT_EXTENSIONS *exts = (const CERT_EXTENSIONS *)pvStructInfo;
722 ret = TRUE;
723 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
725 DWORD size;
727 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
728 if (ret)
729 dataLen += size;
731 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
732 bytesNeeded = 1 + lenBytes + dataLen;
733 if (!pbEncoded)
734 *pcbEncoded = bytesNeeded;
735 else
737 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
738 pcbEncoded, bytesNeeded)))
740 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
741 pbEncoded = *(BYTE **)pbEncoded;
742 *pbEncoded++ = ASN_SEQUENCEOF;
743 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
744 pbEncoded += lenBytes;
745 for (i = 0; i < exts->cExtension; i++)
747 DWORD size = dataLen;
749 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
750 pbEncoded, &size);
751 pbEncoded += size;
752 dataLen -= size;
757 __EXCEPT_PAGE_FAULT
759 SetLastError(STATUS_ACCESS_VIOLATION);
760 ret = FALSE;
762 __ENDTRY
763 return ret;
766 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
767 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
768 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
770 LPCSTR pszObjId = (LPCSTR)pvStructInfo;
771 DWORD bytesNeeded = 0, lenBytes;
772 BOOL ret = TRUE;
773 int firstPos = 0;
774 BYTE firstByte = 0;
776 TRACE("%s\n", debugstr_a(pszObjId));
778 if (pszObjId)
780 const char *ptr;
781 int val1, val2;
783 if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
785 SetLastError(CRYPT_E_ASN1_ERROR);
786 return FALSE;
788 bytesNeeded++;
789 firstByte = val1 * 40 + val2;
790 ptr = pszObjId + firstPos;
791 while (ret && *ptr)
793 int pos;
795 /* note I assume each component is at most 32-bits long in base 2 */
796 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
798 if (val1 >= 0x10000000)
799 bytesNeeded += 5;
800 else if (val1 >= 0x200000)
801 bytesNeeded += 4;
802 else if (val1 >= 0x4000)
803 bytesNeeded += 3;
804 else if (val1 >= 0x80)
805 bytesNeeded += 2;
806 else
807 bytesNeeded += 1;
808 ptr += pos;
809 if (*ptr == '.')
810 ptr++;
812 else
814 SetLastError(CRYPT_E_ASN1_ERROR);
815 return FALSE;
818 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
820 else
821 lenBytes = 1;
822 bytesNeeded += 1 + lenBytes;
823 if (pbEncoded)
825 if (*pcbEncoded < bytesNeeded)
827 SetLastError(ERROR_MORE_DATA);
828 ret = FALSE;
830 else
832 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
833 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
834 pbEncoded += lenBytes;
835 if (pszObjId)
837 const char *ptr;
838 int val, pos;
840 *pbEncoded++ = firstByte;
841 ptr = pszObjId + firstPos;
842 while (ret && *ptr)
844 sscanf(ptr, "%d%n", &val, &pos);
846 unsigned char outBytes[5];
847 int numBytes, i;
849 if (val >= 0x10000000)
850 numBytes = 5;
851 else if (val >= 0x200000)
852 numBytes = 4;
853 else if (val >= 0x4000)
854 numBytes = 3;
855 else if (val >= 0x80)
856 numBytes = 2;
857 else
858 numBytes = 1;
859 for (i = numBytes; i > 0; i--)
861 outBytes[i - 1] = val & 0x7f;
862 val >>= 7;
864 for (i = 0; i < numBytes - 1; i++)
865 *pbEncoded++ = outBytes[i] | 0x80;
866 *pbEncoded++ = outBytes[i];
867 ptr += pos;
868 if (*ptr == '.')
869 ptr++;
875 *pcbEncoded = bytesNeeded;
876 return ret;
879 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
880 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
881 DWORD *pcbEncoded)
883 BOOL ret = TRUE;
884 LPCSTR str = (LPCSTR)value->Value.pbData;
885 DWORD bytesNeeded, lenBytes, encodedLen;
887 encodedLen = value->Value.cbData ? value->Value.cbData : lstrlenA(str);
888 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
889 bytesNeeded = 1 + lenBytes + encodedLen;
890 if (!pbEncoded)
891 *pcbEncoded = bytesNeeded;
892 else
894 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
895 pbEncoded, pcbEncoded, bytesNeeded)))
897 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
898 pbEncoded = *(BYTE **)pbEncoded;
899 *pbEncoded++ = tag;
900 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
901 pbEncoded += lenBytes;
902 memcpy(pbEncoded, str, encodedLen);
905 return ret;
908 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
909 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
910 DWORD *pcbEncoded)
912 BOOL ret = TRUE;
913 LPCWSTR str = (LPCWSTR)value->Value.pbData;
914 DWORD bytesNeeded, lenBytes, strLen;
916 if (value->Value.cbData)
917 strLen = value->Value.cbData / sizeof(WCHAR);
918 else if (value->Value.pbData)
919 strLen = lstrlenW(str);
920 else
921 strLen = 0;
922 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
923 bytesNeeded = 1 + lenBytes + strLen * 2;
924 if (!pbEncoded)
925 *pcbEncoded = bytesNeeded;
926 else
928 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
929 pbEncoded, pcbEncoded, bytesNeeded)))
931 DWORD i;
933 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
934 pbEncoded = *(BYTE **)pbEncoded;
935 *pbEncoded++ = ASN_BMPSTRING;
936 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
937 pbEncoded += lenBytes;
938 for (i = 0; i < strLen; i++)
940 *pbEncoded++ = (str[i] & 0xff00) >> 8;
941 *pbEncoded++ = str[i] & 0x00ff;
945 return ret;
948 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
949 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
950 DWORD *pcbEncoded)
952 BOOL ret = TRUE;
953 LPCWSTR str = (LPCWSTR)value->Value.pbData;
954 DWORD bytesNeeded, lenBytes, encodedLen, strLen;
956 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
957 lstrlenW(str);
958 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
959 NULL);
960 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
961 bytesNeeded = 1 + lenBytes + encodedLen;
962 if (!pbEncoded)
963 *pcbEncoded = bytesNeeded;
964 else
966 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
967 pbEncoded, pcbEncoded, bytesNeeded)))
969 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
970 pbEncoded = *(BYTE **)pbEncoded;
971 *pbEncoded++ = ASN_UTF8STRING;
972 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
973 pbEncoded += lenBytes;
974 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
975 bytesNeeded - lenBytes - 1, NULL, NULL);
978 return ret;
981 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
982 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
983 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
985 BOOL ret = TRUE;
987 __TRY
989 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
991 switch (value->dwValueType)
993 case CERT_RDN_ANY_TYPE:
994 /* explicitly disallowed */
995 SetLastError(E_INVALIDARG);
996 ret = FALSE;
997 break;
998 case CERT_RDN_ENCODED_BLOB:
999 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
1000 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1001 break;
1002 case CERT_RDN_OCTET_STRING:
1003 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1004 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1005 break;
1006 case CERT_RDN_NUMERIC_STRING:
1007 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1008 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1009 break;
1010 case CERT_RDN_PRINTABLE_STRING:
1011 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1012 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1013 break;
1014 case CERT_RDN_TELETEX_STRING:
1015 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1016 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1017 break;
1018 case CERT_RDN_VIDEOTEX_STRING:
1019 ret = CRYPT_AsnEncodeStringCoerce(value,
1020 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1021 break;
1022 case CERT_RDN_IA5_STRING:
1023 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1024 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1025 break;
1026 case CERT_RDN_GRAPHIC_STRING:
1027 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1028 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1029 break;
1030 case CERT_RDN_VISIBLE_STRING:
1031 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1032 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1033 break;
1034 case CERT_RDN_GENERAL_STRING:
1035 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1036 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1037 break;
1038 case CERT_RDN_UNIVERSAL_STRING:
1039 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1040 SetLastError(CRYPT_E_ASN1_CHOICE);
1041 ret = FALSE;
1042 break;
1043 case CERT_RDN_BMP_STRING:
1044 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1045 pbEncoded, pcbEncoded);
1046 break;
1047 case CERT_RDN_UTF8_STRING:
1048 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1049 pbEncoded, pcbEncoded);
1050 break;
1051 default:
1052 SetLastError(CRYPT_E_ASN1_CHOICE);
1053 ret = FALSE;
1056 __EXCEPT_PAGE_FAULT
1058 SetLastError(STATUS_ACCESS_VIOLATION);
1059 ret = FALSE;
1061 __ENDTRY
1062 return ret;
1065 static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1066 CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1067 BYTE *pbEncoded, DWORD *pcbEncoded)
1069 DWORD bytesNeeded = 0, lenBytes, size;
1070 BOOL ret;
1072 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1073 0, NULL, NULL, &size);
1074 if (ret)
1076 bytesNeeded += size;
1077 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1078 * with dwValueType, so "cast" it to get its encoded size
1080 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1081 (CERT_NAME_VALUE *)&attr->dwValueType, 0, NULL, NULL, &size);
1082 if (ret)
1084 bytesNeeded += size;
1085 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1086 bytesNeeded += 1 + lenBytes;
1087 if (pbEncoded)
1089 if (*pcbEncoded < bytesNeeded)
1091 SetLastError(ERROR_MORE_DATA);
1092 ret = FALSE;
1094 else
1096 *pbEncoded++ = ASN_SEQUENCE;
1097 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1098 &lenBytes);
1099 pbEncoded += lenBytes;
1100 size = bytesNeeded - 1 - lenBytes;
1101 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1102 attr->pszObjId, 0, NULL, pbEncoded, &size);
1103 if (ret)
1105 pbEncoded += size;
1106 size = bytesNeeded - 1 - lenBytes - size;
1107 ret = nameValueEncodeFunc(dwCertEncodingType,
1108 NULL, (CERT_NAME_VALUE *)&attr->dwValueType,
1109 0, NULL, pbEncoded, &size);
1110 if (!ret)
1111 *pcbEncoded = size;
1115 if (ret)
1116 *pcbEncoded = bytesNeeded;
1118 else
1120 /* Have to propagate index of failing character */
1121 *pcbEncoded = size;
1124 return ret;
1127 static int BLOBComp(const void *l, const void *r)
1129 const CRYPT_DER_BLOB *a = (const CRYPT_DER_BLOB *)l, *b = (const CRYPT_DER_BLOB *)r;
1130 int ret;
1132 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1133 ret = a->cbData - b->cbData;
1134 return ret;
1137 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1139 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1140 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1141 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1143 const CRYPT_BLOB_ARRAY *set = (const CRYPT_BLOB_ARRAY *)pvStructInfo;
1144 DWORD bytesNeeded = 0, lenBytes, i;
1145 BOOL ret;
1147 for (i = 0; i < set->cBlob; i++)
1148 bytesNeeded += set->rgBlob[i].cbData;
1149 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1150 bytesNeeded += 1 + lenBytes;
1151 if (!pbEncoded)
1153 *pcbEncoded = bytesNeeded;
1154 ret = TRUE;
1156 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1157 pbEncoded, pcbEncoded, bytesNeeded)))
1159 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1160 pbEncoded = *(BYTE **)pbEncoded;
1161 qsort(set->rgBlob, set->cBlob, sizeof(CRYPT_DER_BLOB), BLOBComp);
1162 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1163 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1164 pbEncoded += lenBytes;
1165 for (i = 0; ret && i < set->cBlob; i++)
1167 memcpy(pbEncoded, set->rgBlob[i].pbData, set->rgBlob[i].cbData);
1168 pbEncoded += set->rgBlob[i].cbData;
1171 return ret;
1174 struct DERSetDescriptor
1176 DWORD cItems;
1177 const void *items;
1178 size_t itemSize;
1179 size_t itemOffset;
1180 CryptEncodeObjectExFunc encode;
1183 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,
1184 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1185 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1187 const struct DERSetDescriptor *desc =
1188 (const struct DERSetDescriptor *)pvStructInfo;
1189 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1190 BOOL ret = TRUE;
1191 DWORD i;
1193 if (desc->cItems)
1195 setOf.rgBlob = CryptMemAlloc(desc->cItems * sizeof(CRYPT_DER_BLOB));
1196 if (!setOf.rgBlob)
1197 ret = FALSE;
1198 else
1200 setOf.cBlob = desc->cItems;
1201 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1204 for (i = 0; ret && i < setOf.cBlob; i++)
1206 ret = desc->encode(dwCertEncodingType, lpszStructType,
1207 (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
1208 0, NULL, NULL, &setOf.rgBlob[i].cbData);
1209 if (ret)
1211 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1212 if (!setOf.rgBlob[i].pbData)
1213 ret = FALSE;
1214 else
1215 ret = desc->encode(dwCertEncodingType, lpszStructType,
1216 (const BYTE *)desc->items + i * desc->itemSize +
1217 desc->itemOffset, 0, NULL, setOf.rgBlob[i].pbData,
1218 &setOf.rgBlob[i].cbData);
1220 /* Some functions propagate their errors through the size */
1221 if (!ret)
1222 *pcbEncoded = setOf.rgBlob[i].cbData;
1224 if (ret)
1226 DWORD bytesNeeded = 0, lenBytes;
1227 BOOL ret;
1229 for (i = 0; i < setOf.cBlob; i++)
1230 bytesNeeded += setOf.rgBlob[i].cbData;
1231 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1232 bytesNeeded += 1 + lenBytes;
1233 if (!pbEncoded)
1234 *pcbEncoded = bytesNeeded;
1235 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1236 pbEncoded, pcbEncoded, bytesNeeded)))
1238 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1239 pbEncoded = *(BYTE **)pbEncoded;
1240 qsort(setOf.rgBlob, setOf.cBlob, sizeof(CRYPT_DER_BLOB),
1241 BLOBComp);
1242 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1243 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1244 pbEncoded += lenBytes;
1245 for (i = 0; i < setOf.cBlob; i++)
1247 memcpy(pbEncoded, setOf.rgBlob[i].pbData,
1248 setOf.rgBlob[i].cbData);
1249 pbEncoded += setOf.rgBlob[i].cbData;
1253 for (i = 0; i < setOf.cBlob; i++)
1254 CryptMemFree(setOf.rgBlob[i].pbData);
1255 CryptMemFree(setOf.rgBlob);
1256 return ret;
1259 static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
1260 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1261 DWORD *pcbEncoded)
1263 BOOL ret;
1264 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1266 __TRY
1268 DWORD i;
1270 ret = TRUE;
1271 if (rdn->cRDNAttr)
1273 setOf.cBlob = rdn->cRDNAttr;
1274 setOf.rgBlob = CryptMemAlloc(rdn->cRDNAttr *
1275 sizeof(CRYPT_DER_BLOB));
1276 if (!setOf.rgBlob)
1277 ret = FALSE;
1278 else
1279 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1281 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1283 setOf.rgBlob[i].cbData = 0;
1284 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1285 nameValueEncodeFunc, NULL, &setOf.rgBlob[i].cbData);
1286 if (ret)
1288 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1289 if (!setOf.rgBlob[i].pbData)
1290 ret = FALSE;
1291 else
1292 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1293 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1294 setOf.rgBlob[i].pbData, &setOf.rgBlob[i].cbData);
1296 if (!ret)
1298 /* Have to propagate index of failing character */
1299 *pcbEncoded = setOf.rgBlob[i].cbData;
1302 if (ret)
1303 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1304 pbEncoded, pcbEncoded);
1305 for (i = 0; i < setOf.cBlob; i++)
1306 CryptMemFree(setOf.rgBlob[i].pbData);
1308 __EXCEPT_PAGE_FAULT
1310 SetLastError(STATUS_ACCESS_VIOLATION);
1311 ret = FALSE;
1313 __ENDTRY
1314 CryptMemFree(setOf.rgBlob);
1315 return ret;
1318 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1319 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1320 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1322 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1323 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1324 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1325 DWORD *pcbEncoded)
1327 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1328 BOOL ret;
1330 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1331 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1332 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1333 else
1334 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1335 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1336 return ret;
1339 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1340 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1341 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1343 BOOL ret = TRUE;
1345 __TRY
1347 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1348 DWORD bytesNeeded = 0, lenBytes, size, i;
1350 TRACE("encoding name with %d RDNs\n", info->cRDN);
1351 ret = TRUE;
1352 for (i = 0; ret && i < info->cRDN; i++)
1354 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1355 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1356 if (ret)
1357 bytesNeeded += size;
1358 else
1359 *pcbEncoded = size;
1361 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1362 bytesNeeded += 1 + lenBytes;
1363 if (ret)
1365 if (!pbEncoded)
1366 *pcbEncoded = bytesNeeded;
1367 else
1369 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1370 pbEncoded, pcbEncoded, bytesNeeded)))
1372 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1373 pbEncoded = *(BYTE **)pbEncoded;
1374 *pbEncoded++ = ASN_SEQUENCEOF;
1375 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1376 &lenBytes);
1377 pbEncoded += lenBytes;
1378 for (i = 0; ret && i < info->cRDN; i++)
1380 size = bytesNeeded;
1381 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1382 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1383 pbEncoded, &size);
1384 if (ret)
1386 pbEncoded += size;
1387 bytesNeeded -= size;
1389 else
1390 *pcbEncoded = size;
1396 __EXCEPT_PAGE_FAULT
1398 SetLastError(STATUS_ACCESS_VIOLATION);
1399 ret = FALSE;
1401 __ENDTRY
1402 return ret;
1405 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1406 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1407 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1409 BOOL ret = FALSE;
1411 __TRY
1413 const CRYPT_ATTRIBUTE *attr = (const CRYPT_ATTRIBUTE *)pvStructInfo;
1415 if (!attr->pszObjId)
1416 SetLastError(E_INVALIDARG);
1417 else
1419 struct AsnEncodeSequenceItem items[2] = {
1420 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1421 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1424 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1425 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1426 pcbEncoded);
1429 __EXCEPT_PAGE_FAULT
1431 SetLastError(STATUS_ACCESS_VIOLATION);
1433 __ENDTRY
1434 return ret;
1437 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1438 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1439 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1441 BOOL ret = FALSE;
1443 __TRY
1445 const CRYPT_ATTRIBUTES *attributes =
1446 (const CRYPT_ATTRIBUTES *)pvStructInfo;
1447 struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
1448 sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
1450 ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
1451 &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1453 __EXCEPT_PAGE_FAULT
1455 SetLastError(STATUS_ACCESS_VIOLATION);
1457 __ENDTRY
1458 return ret;
1461 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1462 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
1463 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1464 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1465 DWORD *pcbEncoded)
1467 const CRYPT_CONTENT_INFO *info = (const CRYPT_CONTENT_INFO *)pvStructInfo;
1468 struct AsnEncodeSequenceItem items[2] = {
1469 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1470 { NULL, NULL, 0 },
1472 struct AsnConstructedItem constructed = { 0 };
1473 DWORD cItem = 1;
1475 if (info->Content.cbData)
1477 constructed.tag = 0;
1478 constructed.pvStructInfo = &info->Content;
1479 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1480 items[cItem].pvStructInfo = &constructed;
1481 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1482 cItem++;
1484 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1485 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1488 BOOL CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA *digestedData,
1489 void *pvData, DWORD *pcbData)
1491 struct AsnEncodeSequenceItem items[] = {
1492 { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1493 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
1494 0 },
1495 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1496 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1499 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1500 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
1503 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1504 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1505 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1507 BOOL ret = FALSE;
1509 __TRY
1511 const CRYPT_CONTENT_INFO *info =
1512 (const CRYPT_CONTENT_INFO *)pvStructInfo;
1514 if (!info->pszObjId)
1515 SetLastError(E_INVALIDARG);
1516 else
1517 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
1518 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1519 pcbEncoded);
1521 __EXCEPT_PAGE_FAULT
1523 SetLastError(STATUS_ACCESS_VIOLATION);
1525 __ENDTRY
1526 return ret;
1529 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1530 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1531 DWORD *pcbEncoded)
1533 BOOL ret = TRUE;
1534 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1535 DWORD bytesNeeded, lenBytes, encodedLen;
1537 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1538 lstrlenW(str);
1539 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1540 bytesNeeded = 1 + lenBytes + encodedLen;
1541 if (!pbEncoded)
1542 *pcbEncoded = bytesNeeded;
1543 else
1545 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1546 pbEncoded, pcbEncoded, bytesNeeded)))
1548 DWORD i;
1550 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1551 pbEncoded = *(BYTE **)pbEncoded;
1552 *pbEncoded++ = tag;
1553 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1554 pbEncoded += lenBytes;
1555 for (i = 0; i < encodedLen; i++)
1556 *pbEncoded++ = (BYTE)str[i];
1559 return ret;
1562 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
1563 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1564 DWORD *pcbEncoded)
1566 BOOL ret = TRUE;
1567 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1568 DWORD bytesNeeded, lenBytes, encodedLen;
1570 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1571 lstrlenW(str);
1572 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1573 bytesNeeded = 1 + lenBytes + encodedLen;
1574 if (!pbEncoded)
1575 *pcbEncoded = bytesNeeded;
1576 else
1578 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1579 pbEncoded, pcbEncoded, bytesNeeded)))
1581 DWORD i;
1582 BYTE *ptr;
1584 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1585 ptr = *(BYTE **)pbEncoded;
1586 else
1587 ptr = pbEncoded;
1588 *ptr++ = ASN_NUMERICSTRING;
1589 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
1590 ptr += lenBytes;
1591 for (i = 0; ret && i < encodedLen; i++)
1593 if (isdigitW(str[i]))
1594 *ptr++ = (BYTE)str[i];
1595 else
1597 *pcbEncoded = i;
1598 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
1599 ret = FALSE;
1602 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1603 CryptMemFree(*(BYTE **)pbEncoded);
1606 return ret;
1609 static inline int isprintableW(WCHAR wc)
1611 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
1612 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
1613 wc == '/' || wc == ':' || wc == '=' || wc == '?';
1616 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
1617 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1618 DWORD *pcbEncoded)
1620 BOOL ret = TRUE;
1621 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1622 DWORD bytesNeeded, lenBytes, encodedLen;
1624 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1625 lstrlenW(str);
1626 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1627 bytesNeeded = 1 + lenBytes + encodedLen;
1628 if (!pbEncoded)
1629 *pcbEncoded = bytesNeeded;
1630 else
1632 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1633 pbEncoded, pcbEncoded, bytesNeeded)))
1635 DWORD i;
1636 BYTE *ptr;
1638 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1639 ptr = *(BYTE **)pbEncoded;
1640 else
1641 ptr = pbEncoded;
1642 *ptr++ = ASN_PRINTABLESTRING;
1643 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
1644 ptr += lenBytes;
1645 for (i = 0; ret && i < encodedLen; i++)
1647 if (isprintableW(str[i]))
1648 *ptr++ = (BYTE)str[i];
1649 else
1651 *pcbEncoded = i;
1652 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
1653 ret = FALSE;
1656 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1657 CryptMemFree(*(BYTE **)pbEncoded);
1660 return ret;
1663 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
1664 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1665 DWORD *pcbEncoded)
1667 BOOL ret = TRUE;
1668 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1669 DWORD bytesNeeded, lenBytes, encodedLen;
1671 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1672 lstrlenW(str);
1673 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1674 bytesNeeded = 1 + lenBytes + encodedLen;
1675 if (!pbEncoded)
1676 *pcbEncoded = bytesNeeded;
1677 else
1679 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1680 pbEncoded, pcbEncoded, bytesNeeded)))
1682 DWORD i;
1683 BYTE *ptr;
1685 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1686 ptr = *(BYTE **)pbEncoded;
1687 else
1688 ptr = pbEncoded;
1689 *ptr++ = ASN_IA5STRING;
1690 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
1691 ptr += lenBytes;
1692 for (i = 0; ret && i < encodedLen; i++)
1694 if (str[i] <= 0x7f)
1695 *ptr++ = (BYTE)str[i];
1696 else
1698 *pcbEncoded = i;
1699 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1700 ret = FALSE;
1703 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1704 CryptMemFree(*(BYTE **)pbEncoded);
1707 return ret;
1710 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
1711 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1712 DWORD *pcbEncoded)
1714 BOOL ret = TRUE;
1715 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1716 DWORD bytesNeeded, lenBytes, strLen;
1718 /* FIXME: doesn't handle composite characters */
1719 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1720 lstrlenW(str);
1721 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
1722 bytesNeeded = 1 + lenBytes + strLen * 4;
1723 if (!pbEncoded)
1724 *pcbEncoded = bytesNeeded;
1725 else
1727 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1728 pbEncoded, pcbEncoded, bytesNeeded)))
1730 DWORD i;
1732 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1733 pbEncoded = *(BYTE **)pbEncoded;
1734 *pbEncoded++ = ASN_UNIVERSALSTRING;
1735 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
1736 pbEncoded += lenBytes;
1737 for (i = 0; i < strLen; i++)
1739 *pbEncoded++ = 0;
1740 *pbEncoded++ = 0;
1741 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
1742 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
1746 return ret;
1749 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1750 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1751 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1753 BOOL ret = FALSE;
1755 __TRY
1757 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1759 switch (value->dwValueType)
1761 case CERT_RDN_ANY_TYPE:
1762 case CERT_RDN_ENCODED_BLOB:
1763 case CERT_RDN_OCTET_STRING:
1764 SetLastError(CRYPT_E_NOT_CHAR_STRING);
1765 break;
1766 case CERT_RDN_NUMERIC_STRING:
1767 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
1768 pbEncoded, pcbEncoded);
1769 break;
1770 case CERT_RDN_PRINTABLE_STRING:
1771 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
1772 pbEncoded, pcbEncoded);
1773 break;
1774 case CERT_RDN_TELETEX_STRING:
1775 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
1776 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1777 break;
1778 case CERT_RDN_VIDEOTEX_STRING:
1779 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
1780 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1781 break;
1782 case CERT_RDN_IA5_STRING:
1783 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
1784 pbEncoded, pcbEncoded);
1785 break;
1786 case CERT_RDN_GRAPHIC_STRING:
1787 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
1788 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1789 break;
1790 case CERT_RDN_VISIBLE_STRING:
1791 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
1792 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1793 break;
1794 case CERT_RDN_GENERAL_STRING:
1795 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
1796 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1797 break;
1798 case CERT_RDN_UNIVERSAL_STRING:
1799 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
1800 pbEncoded, pcbEncoded);
1801 break;
1802 case CERT_RDN_BMP_STRING:
1803 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1804 pbEncoded, pcbEncoded);
1805 break;
1806 case CERT_RDN_UTF8_STRING:
1807 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1808 pbEncoded, pcbEncoded);
1809 break;
1810 default:
1811 SetLastError(CRYPT_E_ASN1_CHOICE);
1814 __EXCEPT_PAGE_FAULT
1816 SetLastError(STATUS_ACCESS_VIOLATION);
1818 __ENDTRY
1819 return ret;
1822 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
1823 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1824 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1826 BOOL ret;
1828 __TRY
1830 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1831 DWORD bytesNeeded = 0, lenBytes, size, i;
1833 TRACE("encoding name with %d RDNs\n", info->cRDN);
1834 ret = TRUE;
1835 for (i = 0; ret && i < info->cRDN; i++)
1837 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1838 CRYPT_AsnEncodeNameValue, NULL, &size);
1839 if (ret)
1840 bytesNeeded += size;
1842 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1843 bytesNeeded += 1 + lenBytes;
1844 if (ret)
1846 if (!pbEncoded)
1847 *pcbEncoded = bytesNeeded;
1848 else
1850 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1851 pbEncoded, pcbEncoded, bytesNeeded)))
1853 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1854 pbEncoded = *(BYTE **)pbEncoded;
1855 *pbEncoded++ = ASN_SEQUENCEOF;
1856 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1857 &lenBytes);
1858 pbEncoded += lenBytes;
1859 for (i = 0; ret && i < info->cRDN; i++)
1861 size = bytesNeeded;
1862 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1863 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, pbEncoded,
1864 &size);
1865 if (ret)
1867 pbEncoded += size;
1868 bytesNeeded -= size;
1875 __EXCEPT_PAGE_FAULT
1877 SetLastError(STATUS_ACCESS_VIOLATION);
1878 ret = FALSE;
1880 __ENDTRY
1881 return ret;
1884 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1885 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1886 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1888 BOOL val = *(const BOOL *)pvStructInfo, ret;
1890 TRACE("%d\n", val);
1892 if (!pbEncoded)
1894 *pcbEncoded = 3;
1895 ret = TRUE;
1897 else if (*pcbEncoded < 3)
1899 *pcbEncoded = 3;
1900 SetLastError(ERROR_MORE_DATA);
1901 ret = FALSE;
1903 else
1905 *pcbEncoded = 3;
1906 *pbEncoded++ = ASN_BOOL;
1907 *pbEncoded++ = 1;
1908 *pbEncoded++ = val ? 0xff : 0;
1909 ret = TRUE;
1911 TRACE("returning %d (%08x)\n", ret, GetLastError());
1912 return ret;
1915 static BOOL WINAPI CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType,
1916 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1917 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1919 const CERT_ALT_NAME_ENTRY *entry =
1920 (const CERT_ALT_NAME_ENTRY *)pvStructInfo;
1921 BOOL ret;
1922 DWORD dataLen;
1923 BYTE tag;
1925 ret = TRUE;
1926 switch (entry->dwAltNameChoice)
1928 case CERT_ALT_NAME_RFC822_NAME:
1929 case CERT_ALT_NAME_DNS_NAME:
1930 case CERT_ALT_NAME_URL:
1931 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1932 if (entry->u.pwszURL)
1934 DWORD i;
1936 /* Not + 1: don't encode the NULL-terminator */
1937 dataLen = lstrlenW(entry->u.pwszURL);
1938 for (i = 0; ret && i < dataLen; i++)
1940 if (entry->u.pwszURL[i] > 0x7f)
1942 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1943 ret = FALSE;
1944 *pcbEncoded = i;
1948 else
1949 dataLen = 0;
1950 break;
1951 case CERT_ALT_NAME_DIRECTORY_NAME:
1952 tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1);
1953 dataLen = entry->u.DirectoryName.cbData;
1954 break;
1955 case CERT_ALT_NAME_IP_ADDRESS:
1956 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1957 dataLen = entry->u.IPAddress.cbData;
1958 break;
1959 case CERT_ALT_NAME_REGISTERED_ID:
1961 struct AsnEncodeTagSwappedItem swapped =
1962 { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID,
1963 CRYPT_AsnEncodeOid };
1965 return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded,
1966 pcbEncoded);
1968 case CERT_ALT_NAME_OTHER_NAME:
1969 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
1970 return FALSE;
1971 default:
1972 SetLastError(E_INVALIDARG);
1973 return FALSE;
1975 if (ret)
1977 DWORD bytesNeeded, lenBytes;
1979 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1980 bytesNeeded = 1 + dataLen + lenBytes;
1981 if (!pbEncoded)
1982 *pcbEncoded = bytesNeeded;
1983 else if (*pcbEncoded < bytesNeeded)
1985 SetLastError(ERROR_MORE_DATA);
1986 *pcbEncoded = bytesNeeded;
1987 ret = FALSE;
1989 else
1991 *pbEncoded++ = tag;
1992 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1993 pbEncoded += lenBytes;
1994 switch (entry->dwAltNameChoice)
1996 case CERT_ALT_NAME_RFC822_NAME:
1997 case CERT_ALT_NAME_DNS_NAME:
1998 case CERT_ALT_NAME_URL:
2000 DWORD i;
2002 for (i = 0; i < dataLen; i++)
2003 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
2004 break;
2006 case CERT_ALT_NAME_DIRECTORY_NAME:
2007 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen);
2008 break;
2009 case CERT_ALT_NAME_IP_ADDRESS:
2010 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
2011 break;
2013 if (ret)
2014 *pcbEncoded = bytesNeeded;
2017 TRACE("returning %d (%08x)\n", ret, GetLastError());
2018 return ret;
2021 static BOOL WINAPI CRYPT_AsnEncodeIntegerSwapBytes(DWORD dwCertEncodingType,
2022 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2023 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2025 BOOL ret;
2027 __TRY
2029 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2030 CRYPT_DATA_BLOB newBlob = { blob->cbData, NULL };
2032 ret = TRUE;
2033 if (newBlob.cbData)
2035 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2036 if (newBlob.pbData)
2038 DWORD i;
2040 for (i = 0; i < newBlob.cbData; i++)
2041 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2043 else
2044 ret = FALSE;
2046 if (ret)
2047 ret = CRYPT_AsnEncodeInteger(dwCertEncodingType, lpszStructType,
2048 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2049 CryptMemFree(newBlob.pbData);
2051 __EXCEPT_PAGE_FAULT
2053 SetLastError(STATUS_ACCESS_VIOLATION);
2054 ret = FALSE;
2056 __ENDTRY
2057 return ret;
2060 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
2061 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2062 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2064 BOOL ret;
2066 __TRY
2068 const CERT_AUTHORITY_KEY_ID_INFO *info =
2069 (const CERT_AUTHORITY_KEY_ID_INFO *)pvStructInfo;
2070 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2071 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2072 struct AsnConstructedItem constructed = { 0 };
2073 DWORD cItem = 0, cSwapped = 0;
2075 if (info->KeyId.cbData)
2077 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2078 swapped[cSwapped].pvStructInfo = &info->KeyId;
2079 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2080 items[cItem].pvStructInfo = &swapped[cSwapped];
2081 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2082 cSwapped++;
2083 cItem++;
2085 if (info->CertIssuer.cbData)
2087 constructed.tag = 1;
2088 constructed.pvStructInfo = &info->CertIssuer;
2089 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2090 items[cItem].pvStructInfo = &constructed;
2091 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2092 cItem++;
2094 if (info->CertSerialNumber.cbData)
2096 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2097 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2098 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2099 items[cItem].pvStructInfo = &swapped[cSwapped];
2100 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2101 cSwapped++;
2102 cItem++;
2104 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2105 pEncodePara, pbEncoded, pcbEncoded);
2107 __EXCEPT_PAGE_FAULT
2109 SetLastError(STATUS_ACCESS_VIOLATION);
2110 ret = FALSE;
2112 __ENDTRY
2113 return ret;
2116 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2117 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2118 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2120 BOOL ret;
2122 __TRY
2124 const CERT_ALT_NAME_INFO *info =
2125 (const CERT_ALT_NAME_INFO *)pvStructInfo;
2126 DWORD bytesNeeded, dataLen, lenBytes, i;
2128 ret = TRUE;
2129 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2130 * can't encode an erroneous entry index if it's bigger than this.
2132 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2134 DWORD len;
2136 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, NULL,
2137 &info->rgAltEntry[i], 0, NULL, NULL, &len);
2138 if (ret)
2139 dataLen += len;
2140 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2142 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2143 * the bad character, now set the index of the bad
2144 * entry
2146 *pcbEncoded = (BYTE)i <<
2147 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2150 if (ret)
2152 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2153 bytesNeeded = 1 + lenBytes + dataLen;
2154 if (!pbEncoded)
2156 *pcbEncoded = bytesNeeded;
2157 ret = TRUE;
2159 else
2161 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2162 pbEncoded, pcbEncoded, bytesNeeded)))
2164 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2165 pbEncoded = *(BYTE **)pbEncoded;
2166 *pbEncoded++ = ASN_SEQUENCEOF;
2167 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2168 pbEncoded += lenBytes;
2169 for (i = 0; ret && i < info->cAltEntry; i++)
2171 DWORD len = dataLen;
2173 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType,
2174 NULL, &info->rgAltEntry[i], 0, NULL, pbEncoded, &len);
2175 if (ret)
2177 pbEncoded += len;
2178 dataLen -= len;
2185 __EXCEPT_PAGE_FAULT
2187 SetLastError(STATUS_ACCESS_VIOLATION);
2188 ret = FALSE;
2190 __ENDTRY
2191 return ret;
2194 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2195 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2196 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2198 BOOL ret;
2200 __TRY
2202 const CERT_AUTHORITY_KEY_ID2_INFO *info =
2203 (const CERT_AUTHORITY_KEY_ID2_INFO *)pvStructInfo;
2204 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2205 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2206 DWORD cItem = 0, cSwapped = 0;
2208 if (info->KeyId.cbData)
2210 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2211 swapped[cSwapped].pvStructInfo = &info->KeyId;
2212 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2213 items[cItem].pvStructInfo = &swapped[cSwapped];
2214 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2215 cSwapped++;
2216 cItem++;
2218 if (info->AuthorityCertIssuer.cAltEntry)
2220 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2221 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2222 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2223 items[cItem].pvStructInfo = &swapped[cSwapped];
2224 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2225 cSwapped++;
2226 cItem++;
2228 if (info->AuthorityCertSerialNumber.cbData)
2230 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2231 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2232 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2233 items[cItem].pvStructInfo = &swapped[cSwapped];
2234 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2235 cSwapped++;
2236 cItem++;
2238 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2239 pEncodePara, pbEncoded, pcbEncoded);
2241 __EXCEPT_PAGE_FAULT
2243 SetLastError(STATUS_ACCESS_VIOLATION);
2244 ret = FALSE;
2246 __ENDTRY
2247 return ret;
2250 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2251 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2252 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2254 BOOL ret;
2256 __TRY
2258 const CERT_BASIC_CONSTRAINTS_INFO *info =
2259 (const CERT_BASIC_CONSTRAINTS_INFO *)pvStructInfo;
2260 struct AsnEncodeSequenceItem items[3] = {
2261 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2262 { 0 }
2264 DWORD cItem = 1;
2266 if (info->fPathLenConstraint)
2268 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2269 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2270 cItem++;
2272 if (info->cSubtreesConstraint)
2274 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2275 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2276 cItem++;
2278 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2279 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2281 __EXCEPT_PAGE_FAULT
2283 SetLastError(STATUS_ACCESS_VIOLATION);
2284 ret = FALSE;
2286 __ENDTRY
2287 return ret;
2290 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2291 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2292 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2294 BOOL ret;
2296 __TRY
2298 const CERT_BASIC_CONSTRAINTS2_INFO *info =
2299 (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
2300 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2301 DWORD cItem = 0;
2303 if (info->fCA)
2305 items[cItem].pvStructInfo = &info->fCA;
2306 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2307 cItem++;
2309 if (info->fPathLenConstraint)
2311 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2312 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2313 cItem++;
2315 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2316 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2318 __EXCEPT_PAGE_FAULT
2320 SetLastError(STATUS_ACCESS_VIOLATION);
2321 ret = FALSE;
2323 __ENDTRY
2324 return ret;
2327 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
2328 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2329 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2331 BOOL ret;
2333 __TRY
2335 const BLOBHEADER *hdr =
2336 (const BLOBHEADER *)pvStructInfo;
2338 if (hdr->bType != PUBLICKEYBLOB)
2340 SetLastError(E_INVALIDARG);
2341 ret = FALSE;
2343 else
2345 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
2346 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
2347 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
2348 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
2349 struct AsnEncodeSequenceItem items[] = {
2350 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
2351 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
2354 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2355 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
2356 pcbEncoded);
2359 __EXCEPT_PAGE_FAULT
2361 SetLastError(STATUS_ACCESS_VIOLATION);
2362 ret = FALSE;
2364 __ENDTRY
2365 return ret;
2368 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
2369 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2370 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2372 BOOL ret;
2374 __TRY
2376 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2377 DWORD bytesNeeded, lenBytes;
2379 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
2380 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
2382 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
2383 bytesNeeded = 1 + lenBytes + blob->cbData;
2384 if (!pbEncoded)
2386 *pcbEncoded = bytesNeeded;
2387 ret = TRUE;
2389 else
2391 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2392 pcbEncoded, bytesNeeded)))
2394 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2395 pbEncoded = *(BYTE **)pbEncoded;
2396 *pbEncoded++ = ASN_OCTETSTRING;
2397 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
2398 pbEncoded += lenBytes;
2399 if (blob->cbData)
2400 memcpy(pbEncoded, blob->pbData, blob->cbData);
2404 __EXCEPT_PAGE_FAULT
2406 SetLastError(STATUS_ACCESS_VIOLATION);
2407 ret = FALSE;
2409 __ENDTRY
2410 TRACE("returning %d (%08x)\n", ret, GetLastError());
2411 return ret;
2414 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
2415 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2416 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2418 BOOL ret;
2420 __TRY
2422 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2423 DWORD bytesNeeded, lenBytes, dataBytes;
2424 BYTE unusedBits;
2426 /* yep, MS allows cUnusedBits to be >= 8 */
2427 if (!blob->cUnusedBits)
2429 dataBytes = blob->cbData;
2430 unusedBits = 0;
2432 else if (blob->cbData * 8 > blob->cUnusedBits)
2434 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
2435 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
2436 blob->cUnusedBits;
2438 else
2440 dataBytes = 0;
2441 unusedBits = 0;
2443 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
2444 bytesNeeded = 1 + lenBytes + dataBytes + 1;
2445 if (!pbEncoded)
2447 *pcbEncoded = bytesNeeded;
2448 ret = TRUE;
2450 else
2452 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2453 pcbEncoded, bytesNeeded)))
2455 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2456 pbEncoded = *(BYTE **)pbEncoded;
2457 *pbEncoded++ = ASN_BITSTRING;
2458 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
2459 pbEncoded += lenBytes;
2460 *pbEncoded++ = unusedBits;
2461 if (dataBytes)
2463 BYTE mask = 0xff << unusedBits;
2465 if (dataBytes > 1)
2467 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
2468 pbEncoded += dataBytes - 1;
2470 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
2475 __EXCEPT_PAGE_FAULT
2477 SetLastError(STATUS_ACCESS_VIOLATION);
2478 ret = FALSE;
2480 __ENDTRY
2481 return ret;
2484 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
2485 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2486 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2488 BOOL ret;
2490 __TRY
2492 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2493 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
2495 ret = TRUE;
2496 if (newBlob.cbData)
2498 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2499 if (newBlob.pbData)
2501 DWORD i;
2503 for (i = 0; i < newBlob.cbData; i++)
2504 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2506 else
2507 ret = FALSE;
2509 if (ret)
2510 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
2511 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2512 CryptMemFree(newBlob.pbData);
2514 __EXCEPT_PAGE_FAULT
2516 SetLastError(STATUS_ACCESS_VIOLATION);
2517 ret = FALSE;
2519 __ENDTRY
2520 return ret;
2523 BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
2524 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2525 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2527 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
2529 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
2530 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2533 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
2534 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2535 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2537 BOOL ret;
2539 __TRY
2541 DWORD significantBytes, lenBytes;
2542 BYTE padByte = 0, bytesNeeded;
2543 BOOL pad = FALSE;
2544 const CRYPT_INTEGER_BLOB *blob =
2545 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2547 significantBytes = blob->cbData;
2548 if (significantBytes)
2550 if (blob->pbData[significantBytes - 1] & 0x80)
2552 /* negative, lop off leading (little-endian) 0xffs */
2553 for (; significantBytes > 0 &&
2554 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
2556 if (blob->pbData[significantBytes - 1] < 0x80)
2558 padByte = 0xff;
2559 pad = TRUE;
2562 else
2564 /* positive, lop off leading (little-endian) zeroes */
2565 for (; significantBytes > 0 &&
2566 !blob->pbData[significantBytes - 1]; significantBytes--)
2568 if (significantBytes == 0)
2569 significantBytes = 1;
2570 if (blob->pbData[significantBytes - 1] > 0x7f)
2572 padByte = 0;
2573 pad = TRUE;
2577 if (pad)
2578 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2579 else
2580 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2581 bytesNeeded = 1 + lenBytes + significantBytes;
2582 if (pad)
2583 bytesNeeded++;
2584 if (!pbEncoded)
2586 *pcbEncoded = bytesNeeded;
2587 ret = TRUE;
2589 else
2591 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2592 pcbEncoded, bytesNeeded)))
2594 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2595 pbEncoded = *(BYTE **)pbEncoded;
2596 *pbEncoded++ = ASN_INTEGER;
2597 if (pad)
2599 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2600 pbEncoded += lenBytes;
2601 *pbEncoded++ = padByte;
2603 else
2605 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2606 pbEncoded += lenBytes;
2608 for (; significantBytes > 0; significantBytes--)
2609 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2613 __EXCEPT_PAGE_FAULT
2615 SetLastError(STATUS_ACCESS_VIOLATION);
2616 ret = FALSE;
2618 __ENDTRY
2619 return ret;
2622 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
2623 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2624 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2626 BOOL ret;
2628 __TRY
2630 DWORD significantBytes, lenBytes;
2631 BYTE bytesNeeded;
2632 BOOL pad = FALSE;
2633 const CRYPT_INTEGER_BLOB *blob =
2634 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2636 significantBytes = blob->cbData;
2637 if (significantBytes)
2639 /* positive, lop off leading (little-endian) zeroes */
2640 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
2641 significantBytes--)
2643 if (significantBytes == 0)
2644 significantBytes = 1;
2645 if (blob->pbData[significantBytes - 1] > 0x7f)
2646 pad = TRUE;
2648 if (pad)
2649 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2650 else
2651 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2652 bytesNeeded = 1 + lenBytes + significantBytes;
2653 if (pad)
2654 bytesNeeded++;
2655 if (!pbEncoded)
2657 *pcbEncoded = bytesNeeded;
2658 ret = TRUE;
2660 else
2662 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2663 pcbEncoded, bytesNeeded)))
2665 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2666 pbEncoded = *(BYTE **)pbEncoded;
2667 *pbEncoded++ = ASN_INTEGER;
2668 if (pad)
2670 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2671 pbEncoded += lenBytes;
2672 *pbEncoded++ = 0;
2674 else
2676 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2677 pbEncoded += lenBytes;
2679 for (; significantBytes > 0; significantBytes--)
2680 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2684 __EXCEPT_PAGE_FAULT
2686 SetLastError(STATUS_ACCESS_VIOLATION);
2687 ret = FALSE;
2689 __ENDTRY
2690 return ret;
2693 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
2694 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2695 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2697 CRYPT_INTEGER_BLOB blob;
2698 BOOL ret;
2700 /* Encode as an unsigned integer, then change the tag to enumerated */
2701 blob.cbData = sizeof(DWORD);
2702 blob.pbData = (BYTE *)pvStructInfo;
2703 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
2704 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2705 if (ret && pbEncoded)
2707 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2708 pbEncoded = *(BYTE **)pbEncoded;
2709 pbEncoded[0] = ASN_ENUMERATED;
2711 return ret;
2714 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
2715 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2716 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2718 BOOL ret;
2720 __TRY
2722 SYSTEMTIME sysTime;
2723 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2724 * temporary buffer because the output buffer is not NULL-terminated.
2726 char buf[16];
2727 static const DWORD bytesNeeded = sizeof(buf) - 1;
2729 if (!pbEncoded)
2731 *pcbEncoded = bytesNeeded;
2732 ret = TRUE;
2734 else
2736 /* Sanity check the year, this is a two-digit year format */
2737 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2738 &sysTime);
2739 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
2741 SetLastError(CRYPT_E_BAD_ENCODE);
2742 ret = FALSE;
2744 if (ret)
2746 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2747 pbEncoded, pcbEncoded, bytesNeeded)))
2749 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2750 pbEncoded = *(BYTE **)pbEncoded;
2751 buf[0] = ASN_UTCTIME;
2752 buf[1] = bytesNeeded - 2;
2753 snprintf(buf + 2, sizeof(buf) - 2,
2754 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
2755 sysTime.wYear - 2000 : sysTime.wYear - 1900,
2756 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2757 sysTime.wMinute, sysTime.wSecond);
2758 memcpy(pbEncoded, buf, bytesNeeded);
2763 __EXCEPT_PAGE_FAULT
2765 SetLastError(STATUS_ACCESS_VIOLATION);
2766 ret = FALSE;
2768 __ENDTRY
2769 return ret;
2772 static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
2773 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2774 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2776 BOOL ret;
2778 __TRY
2780 SYSTEMTIME sysTime;
2781 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2782 * temporary buffer because the output buffer is not NULL-terminated.
2784 char buf[18];
2785 static const DWORD bytesNeeded = sizeof(buf) - 1;
2787 if (!pbEncoded)
2789 *pcbEncoded = bytesNeeded;
2790 ret = TRUE;
2792 else
2794 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2795 &sysTime);
2796 if (ret)
2797 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2798 pcbEncoded, bytesNeeded);
2799 if (ret)
2801 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2802 pbEncoded = *(BYTE **)pbEncoded;
2803 buf[0] = ASN_GENERALTIME;
2804 buf[1] = bytesNeeded - 2;
2805 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
2806 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2807 sysTime.wMinute, sysTime.wSecond);
2808 memcpy(pbEncoded, buf, bytesNeeded);
2812 __EXCEPT_PAGE_FAULT
2814 SetLastError(STATUS_ACCESS_VIOLATION);
2815 ret = FALSE;
2817 __ENDTRY
2818 return ret;
2821 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
2822 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2823 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2825 BOOL ret;
2827 __TRY
2829 SYSTEMTIME sysTime;
2831 /* Check the year, if it's in the UTCTime range call that encode func */
2832 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
2833 return FALSE;
2834 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
2835 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
2836 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2837 else
2838 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
2839 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
2840 pcbEncoded);
2842 __EXCEPT_PAGE_FAULT
2844 SetLastError(STATUS_ACCESS_VIOLATION);
2845 ret = FALSE;
2847 __ENDTRY
2848 return ret;
2851 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
2852 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2853 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2855 BOOL ret;
2857 __TRY
2859 DWORD bytesNeeded, dataLen, lenBytes, i;
2860 const CRYPT_SEQUENCE_OF_ANY *seq =
2861 (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2863 for (i = 0, dataLen = 0; i < seq->cValue; i++)
2864 dataLen += seq->rgValue[i].cbData;
2865 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2866 bytesNeeded = 1 + lenBytes + dataLen;
2867 if (!pbEncoded)
2869 *pcbEncoded = bytesNeeded;
2870 ret = TRUE;
2872 else
2874 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2875 pcbEncoded, bytesNeeded)))
2877 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2878 pbEncoded = *(BYTE **)pbEncoded;
2879 *pbEncoded++ = ASN_SEQUENCEOF;
2880 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2881 pbEncoded += lenBytes;
2882 for (i = 0; i < seq->cValue; i++)
2884 memcpy(pbEncoded, seq->rgValue[i].pbData,
2885 seq->rgValue[i].cbData);
2886 pbEncoded += seq->rgValue[i].cbData;
2891 __EXCEPT_PAGE_FAULT
2893 SetLastError(STATUS_ACCESS_VIOLATION);
2894 ret = FALSE;
2896 __ENDTRY
2897 return ret;
2900 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
2901 BYTE *pbEncoded, DWORD *pcbEncoded)
2903 BOOL ret = TRUE;
2904 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2905 struct AsnConstructedItem constructed = { 0 };
2906 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2907 DWORD cItem = 0, cSwapped = 0;
2909 switch (distPoint->DistPointName.dwDistPointNameChoice)
2911 case CRL_DIST_POINT_NO_NAME:
2912 /* do nothing */
2913 break;
2914 case CRL_DIST_POINT_FULL_NAME:
2915 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
2916 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
2917 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2918 constructed.tag = 0;
2919 constructed.pvStructInfo = &swapped[cSwapped];
2920 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
2921 items[cItem].pvStructInfo = &constructed;
2922 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2923 cSwapped++;
2924 cItem++;
2925 break;
2926 case CRL_DIST_POINT_ISSUER_RDN_NAME:
2927 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2928 ret = FALSE;
2929 break;
2930 default:
2931 ret = FALSE;
2933 if (ret && distPoint->ReasonFlags.cbData)
2935 swapped[cSwapped].tag = ASN_CONTEXT | 1;
2936 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
2937 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
2938 items[cItem].pvStructInfo = &swapped[cSwapped];
2939 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2940 cSwapped++;
2941 cItem++;
2943 if (ret && distPoint->CRLIssuer.cAltEntry)
2945 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
2946 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
2947 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2948 items[cItem].pvStructInfo = &swapped[cSwapped];
2949 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2950 cSwapped++;
2951 cItem++;
2953 if (ret)
2954 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
2955 pbEncoded, pcbEncoded);
2956 return ret;
2959 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
2960 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2961 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2963 BOOL ret;
2965 __TRY
2967 const CRL_DIST_POINTS_INFO *info =
2968 (const CRL_DIST_POINTS_INFO *)pvStructInfo;
2970 if (!info->cDistPoint)
2972 SetLastError(E_INVALIDARG);
2973 ret = FALSE;
2975 else
2977 DWORD bytesNeeded, dataLen, lenBytes, i;
2979 ret = TRUE;
2980 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
2982 DWORD len;
2984 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
2985 &len);
2986 if (ret)
2987 dataLen += len;
2988 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2990 /* Have to propagate index of failing character */
2991 *pcbEncoded = len;
2994 if (ret)
2996 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2997 bytesNeeded = 1 + lenBytes + dataLen;
2998 if (!pbEncoded)
3000 *pcbEncoded = bytesNeeded;
3001 ret = TRUE;
3003 else
3005 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3006 pbEncoded, pcbEncoded, bytesNeeded)))
3008 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3009 pbEncoded = *(BYTE **)pbEncoded;
3010 *pbEncoded++ = ASN_SEQUENCEOF;
3011 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
3012 pbEncoded += lenBytes;
3013 for (i = 0; ret && i < info->cDistPoint; i++)
3015 DWORD len = dataLen;
3017 ret = CRYPT_AsnEncodeDistPoint(
3018 &info->rgDistPoint[i], pbEncoded, &len);
3019 if (ret)
3021 pbEncoded += len;
3022 dataLen -= len;
3030 __EXCEPT_PAGE_FAULT
3032 SetLastError(STATUS_ACCESS_VIOLATION);
3033 ret = FALSE;
3035 __ENDTRY
3036 return ret;
3039 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3040 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3041 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3043 BOOL ret;
3045 __TRY
3047 const CERT_ENHKEY_USAGE *usage =
3048 (const CERT_ENHKEY_USAGE *)pvStructInfo;
3049 DWORD bytesNeeded = 0, lenBytes, size, i;
3051 ret = TRUE;
3052 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3054 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3055 usage->rgpszUsageIdentifier[i],
3056 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
3057 if (ret)
3058 bytesNeeded += size;
3060 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3061 bytesNeeded += 1 + lenBytes;
3062 if (ret)
3064 if (!pbEncoded)
3065 *pcbEncoded = bytesNeeded;
3066 else
3068 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3069 pbEncoded, pcbEncoded, bytesNeeded)))
3071 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3072 pbEncoded = *(BYTE **)pbEncoded;
3073 *pbEncoded++ = ASN_SEQUENCEOF;
3074 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
3075 &lenBytes);
3076 pbEncoded += lenBytes;
3077 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3079 size = bytesNeeded;
3080 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3081 usage->rgpszUsageIdentifier[i],
3082 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
3083 &size);
3084 if (ret)
3086 pbEncoded += size;
3087 bytesNeeded -= size;
3094 __EXCEPT_PAGE_FAULT
3096 SetLastError(STATUS_ACCESS_VIOLATION);
3097 ret = FALSE;
3099 __ENDTRY
3100 return ret;
3103 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
3104 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3105 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3107 BOOL ret;
3109 __TRY
3111 const CRL_ISSUING_DIST_POINT *point =
3112 (const CRL_ISSUING_DIST_POINT *)pvStructInfo;
3113 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3114 struct AsnConstructedItem constructed = { 0 };
3115 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3116 DWORD cItem = 0, cSwapped = 0;
3118 ret = TRUE;
3119 switch (point->DistPointName.dwDistPointNameChoice)
3121 case CRL_DIST_POINT_NO_NAME:
3122 /* do nothing */
3123 break;
3124 case CRL_DIST_POINT_FULL_NAME:
3125 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3126 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3127 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3128 constructed.tag = 0;
3129 constructed.pvStructInfo = &swapped[cSwapped];
3130 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3131 items[cItem].pvStructInfo = &constructed;
3132 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3133 cSwapped++;
3134 cItem++;
3135 break;
3136 default:
3137 SetLastError(E_INVALIDARG);
3138 ret = FALSE;
3140 if (ret && point->fOnlyContainsUserCerts)
3142 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3143 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3144 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3145 items[cItem].pvStructInfo = &swapped[cSwapped];
3146 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3147 cSwapped++;
3148 cItem++;
3150 if (ret && point->fOnlyContainsCACerts)
3152 swapped[cSwapped].tag = ASN_CONTEXT | 2;
3153 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3154 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3155 items[cItem].pvStructInfo = &swapped[cSwapped];
3156 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3157 cSwapped++;
3158 cItem++;
3160 if (ret && point->OnlySomeReasonFlags.cbData)
3162 swapped[cSwapped].tag = ASN_CONTEXT | 3;
3163 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3164 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3165 items[cItem].pvStructInfo = &swapped[cSwapped];
3166 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3167 cSwapped++;
3168 cItem++;
3170 if (ret && point->fIndirectCRL)
3172 swapped[cSwapped].tag = ASN_CONTEXT | 4;
3173 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
3174 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3175 items[cItem].pvStructInfo = &swapped[cSwapped];
3176 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3177 cSwapped++;
3178 cItem++;
3180 if (ret)
3181 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3182 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3184 __EXCEPT_PAGE_FAULT
3186 SetLastError(STATUS_ACCESS_VIOLATION);
3187 ret = FALSE;
3189 __ENDTRY
3190 return ret;
3193 static BOOL WINAPI CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType,
3194 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3195 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3197 BOOL ret;
3198 const CERT_GENERAL_SUBTREE *subtree =
3199 (const CERT_GENERAL_SUBTREE *)pvStructInfo;
3200 struct AsnEncodeSequenceItem items[3] = {
3201 { &subtree->Base, CRYPT_AsnEncodeAltNameEntry, 0 },
3202 { 0 }
3204 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3205 DWORD cItem = 1, cSwapped = 0;
3207 if (subtree->dwMinimum)
3209 swapped[cSwapped].tag = ASN_CONTEXT | 0;
3210 swapped[cSwapped].pvStructInfo = &subtree->dwMinimum;
3211 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3212 items[cItem].pvStructInfo = &swapped[cSwapped];
3213 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3214 cSwapped++;
3215 cItem++;
3217 if (subtree->fMaximum)
3219 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3220 swapped[cSwapped].pvStructInfo = &subtree->dwMaximum;
3221 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3222 items[cItem].pvStructInfo = &swapped[cSwapped];
3223 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3224 cSwapped++;
3225 cItem++;
3227 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags,
3228 pEncodePara, pbEncoded, pcbEncoded);
3229 return ret;
3232 static BOOL WINAPI CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType,
3233 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3234 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3236 BOOL ret = FALSE;
3237 CRYPT_BLOB_ARRAY permitted = { 0, NULL }, excluded = { 0, NULL };
3239 TRACE("%p\n", pvStructInfo);
3241 __TRY
3243 const CERT_NAME_CONSTRAINTS_INFO *constraints =
3244 (const CERT_NAME_CONSTRAINTS_INFO *)pvStructInfo;
3245 struct AsnEncodeSequenceItem items[2] = { { 0 } };
3246 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3247 DWORD i, cItem = 0, cSwapped = 0;
3249 ret = TRUE;
3250 if (constraints->cPermittedSubtree)
3252 permitted.rgBlob = CryptMemAlloc(
3253 constraints->cPermittedSubtree * sizeof(CRYPT_DER_BLOB));
3254 if (permitted.rgBlob)
3256 permitted.cBlob = constraints->cPermittedSubtree;
3257 memset(permitted.rgBlob, 0,
3258 permitted.cBlob * sizeof(CRYPT_DER_BLOB));
3259 for (i = 0; ret && i < permitted.cBlob; i++)
3260 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3261 NULL, &constraints->rgPermittedSubtree[i],
3262 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3263 (BYTE *)&permitted.rgBlob[i].pbData,
3264 &permitted.rgBlob[i].cbData);
3265 if (ret)
3267 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3268 swapped[cSwapped].pvStructInfo = &permitted;
3269 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3270 items[cItem].pvStructInfo = &swapped[cSwapped];
3271 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3272 cSwapped++;
3273 cItem++;
3276 else
3277 ret = FALSE;
3279 if (constraints->cExcludedSubtree)
3281 excluded.rgBlob = CryptMemAlloc(
3282 constraints->cExcludedSubtree * sizeof(CRYPT_DER_BLOB));
3283 if (excluded.rgBlob)
3285 excluded.cBlob = constraints->cExcludedSubtree;
3286 memset(excluded.rgBlob, 0,
3287 excluded.cBlob * sizeof(CRYPT_DER_BLOB));
3288 for (i = 0; ret && i < excluded.cBlob; i++)
3289 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3290 NULL, &constraints->rgExcludedSubtree[i],
3291 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3292 (BYTE *)&excluded.rgBlob[i].pbData,
3293 &excluded.rgBlob[i].cbData);
3294 if (ret)
3296 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
3297 swapped[cSwapped].pvStructInfo = &excluded;
3298 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3299 items[cItem].pvStructInfo = &swapped[cSwapped];
3300 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3301 cSwapped++;
3302 cItem++;
3305 else
3306 ret = FALSE;
3308 if (ret)
3309 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3310 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3311 for (i = 0; i < permitted.cBlob; i++)
3312 LocalFree(permitted.rgBlob[i].pbData);
3313 for (i = 0; i < excluded.cBlob; i++)
3314 LocalFree(excluded.rgBlob[i].pbData);
3316 __EXCEPT_PAGE_FAULT
3318 SetLastError(STATUS_ACCESS_VIOLATION);
3320 __ENDTRY
3321 CryptMemFree(permitted.rgBlob);
3322 CryptMemFree(excluded.rgBlob);
3323 TRACE("returning %d\n", ret);
3324 return ret;
3327 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
3328 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3329 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3330 DWORD *pcbEncoded)
3332 BOOL ret;
3333 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3334 (const CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3335 struct AsnEncodeSequenceItem items[] = {
3336 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
3337 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
3340 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3341 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3342 pcbEncoded);
3343 return ret;
3346 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
3347 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3348 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3350 BOOL ret = FALSE;
3352 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
3354 SetLastError(E_INVALIDARG);
3355 return FALSE;
3358 __TRY
3360 const CMSG_SIGNER_INFO *info = (const CMSG_SIGNER_INFO *)pvStructInfo;
3362 if (!info->Issuer.cbData)
3363 SetLastError(E_INVALIDARG);
3364 else
3366 struct AsnEncodeSequenceItem items[7] = {
3367 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
3368 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
3369 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
3370 0 },
3372 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3373 DWORD cItem = 3, cSwapped = 0;
3375 if (info->AuthAttrs.cAttr)
3377 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3378 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
3379 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3380 items[cItem].pvStructInfo = &swapped[cSwapped];
3381 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3382 cSwapped++;
3383 cItem++;
3385 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
3386 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
3387 cItem++;
3388 items[cItem].pvStructInfo = &info->EncryptedHash;
3389 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
3390 cItem++;
3391 if (info->UnauthAttrs.cAttr)
3393 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
3394 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
3395 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3396 items[cItem].pvStructInfo = &swapped[cSwapped];
3397 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3398 cSwapped++;
3399 cItem++;
3401 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3402 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3405 __EXCEPT_PAGE_FAULT
3407 SetLastError(STATUS_ACCESS_VIOLATION);
3409 __ENDTRY
3410 return ret;
3413 BOOL CRYPT_AsnEncodePKCSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
3414 DWORD *pcbData)
3416 struct AsnEncodeSequenceItem items[7] = {
3417 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
3419 struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 };
3420 struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 };
3421 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3422 DWORD cItem = 1, cSwapped = 0;
3423 BOOL ret = TRUE;
3425 if (signedInfo->cSignerInfo)
3427 digestAlgorithmsSet.cItems = signedInfo->cSignerInfo;
3428 digestAlgorithmsSet.items = signedInfo->rgSignerInfo;
3429 digestAlgorithmsSet.itemSize = sizeof(CMSG_SIGNER_INFO);
3430 digestAlgorithmsSet.itemOffset =
3431 offsetof(CMSG_SIGNER_INFO, HashAlgorithm);
3432 digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
3433 items[cItem].pvStructInfo = &digestAlgorithmsSet;
3434 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3435 cItem++;
3437 items[cItem].pvStructInfo = &signedInfo->content;
3438 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal;
3439 cItem++;
3440 if (signedInfo->cCertEncoded)
3442 certSet.cItems = signedInfo->cCertEncoded;
3443 certSet.items = signedInfo->rgCertEncoded;
3444 certSet.itemSize = sizeof(CERT_BLOB);
3445 certSet.itemOffset = 0;
3446 certSet.encode = CRYPT_CopyEncodedBlob;
3447 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0;
3448 swapped[cSwapped].pvStructInfo = &certSet;
3449 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3450 items[cItem].pvStructInfo = &swapped[cSwapped];
3451 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3452 cSwapped++;
3453 cItem++;
3455 if (signedInfo->cCrlEncoded)
3457 crlSet.cItems = signedInfo->cCrlEncoded;
3458 crlSet.items = signedInfo->rgCrlEncoded;
3459 crlSet.itemSize = sizeof(CRL_BLOB);
3460 crlSet.itemOffset = 0;
3461 crlSet.encode = CRYPT_CopyEncodedBlob;
3462 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
3463 swapped[cSwapped].pvStructInfo = &crlSet;
3464 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3465 items[cItem].pvStructInfo = &swapped[cSwapped];
3466 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3467 cSwapped++;
3468 cItem++;
3470 if (ret && signedInfo->cSignerInfo)
3472 signerSet.cItems = signedInfo->cSignerInfo;
3473 signerSet.items = signedInfo->rgSignerInfo;
3474 signerSet.itemSize = sizeof(CMSG_SIGNER_INFO);
3475 signerSet.itemOffset = 0;
3476 signerSet.encode = CRYPT_AsnEncodePKCSSignerInfo;
3477 items[cItem].pvStructInfo = &signerSet;
3478 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3479 cItem++;
3481 if (ret)
3482 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
3483 items, cItem, 0, NULL, pvData, pcbData);
3485 return ret;
3488 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
3489 LPCSTR lpszStructType)
3491 CryptEncodeObjectExFunc encodeFunc = NULL;
3493 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3494 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3496 SetLastError(ERROR_FILE_NOT_FOUND);
3497 return NULL;
3500 if (!HIWORD(lpszStructType))
3502 switch (LOWORD(lpszStructType))
3504 case LOWORD(X509_CERT):
3505 encodeFunc = CRYPT_AsnEncodeCert;
3506 break;
3507 case LOWORD(X509_CERT_TO_BE_SIGNED):
3508 encodeFunc = CRYPT_AsnEncodeCertInfo;
3509 break;
3510 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
3511 encodeFunc = CRYPT_AsnEncodeCRLInfo;
3512 break;
3513 case LOWORD(X509_EXTENSIONS):
3514 encodeFunc = CRYPT_AsnEncodeExtensions;
3515 break;
3516 case LOWORD(X509_NAME_VALUE):
3517 encodeFunc = CRYPT_AsnEncodeNameValue;
3518 break;
3519 case LOWORD(X509_NAME):
3520 encodeFunc = CRYPT_AsnEncodeName;
3521 break;
3522 case LOWORD(X509_PUBLIC_KEY_INFO):
3523 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
3524 break;
3525 case LOWORD(X509_AUTHORITY_KEY_ID):
3526 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3527 break;
3528 case LOWORD(X509_ALTERNATE_NAME):
3529 encodeFunc = CRYPT_AsnEncodeAltName;
3530 break;
3531 case LOWORD(X509_BASIC_CONSTRAINTS):
3532 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3533 break;
3534 case LOWORD(X509_BASIC_CONSTRAINTS2):
3535 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3536 break;
3537 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
3538 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
3539 break;
3540 case LOWORD(X509_UNICODE_NAME):
3541 encodeFunc = CRYPT_AsnEncodeUnicodeName;
3542 break;
3543 case LOWORD(PKCS_CONTENT_INFO):
3544 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
3545 break;
3546 case LOWORD(PKCS_ATTRIBUTE):
3547 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
3548 break;
3549 case LOWORD(X509_UNICODE_NAME_VALUE):
3550 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
3551 break;
3552 case LOWORD(X509_OCTET_STRING):
3553 encodeFunc = CRYPT_AsnEncodeOctets;
3554 break;
3555 case LOWORD(X509_BITS):
3556 case LOWORD(X509_KEY_USAGE):
3557 encodeFunc = CRYPT_AsnEncodeBits;
3558 break;
3559 case LOWORD(X509_INTEGER):
3560 encodeFunc = CRYPT_AsnEncodeInt;
3561 break;
3562 case LOWORD(X509_MULTI_BYTE_INTEGER):
3563 encodeFunc = CRYPT_AsnEncodeInteger;
3564 break;
3565 case LOWORD(X509_MULTI_BYTE_UINT):
3566 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
3567 break;
3568 case LOWORD(X509_ENUMERATED):
3569 encodeFunc = CRYPT_AsnEncodeEnumerated;
3570 break;
3571 case LOWORD(X509_CHOICE_OF_TIME):
3572 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
3573 break;
3574 case LOWORD(X509_AUTHORITY_KEY_ID2):
3575 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3576 break;
3577 case LOWORD(X509_SEQUENCE_OF_ANY):
3578 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
3579 break;
3580 case LOWORD(PKCS_UTC_TIME):
3581 encodeFunc = CRYPT_AsnEncodeUtcTime;
3582 break;
3583 case LOWORD(X509_CRL_DIST_POINTS):
3584 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3585 break;
3586 case LOWORD(X509_ENHANCED_KEY_USAGE):
3587 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3588 break;
3589 case LOWORD(PKCS_ATTRIBUTES):
3590 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3591 break;
3592 case LOWORD(X509_ISSUING_DIST_POINT):
3593 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3594 break;
3595 case LOWORD(X509_NAME_CONSTRAINTS):
3596 encodeFunc = CRYPT_AsnEncodeNameConstraints;
3597 break;
3598 case LOWORD(PKCS7_SIGNER_INFO):
3599 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
3600 break;
3603 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3604 encodeFunc = CRYPT_AsnEncodeExtensions;
3605 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3606 encodeFunc = CRYPT_AsnEncodeUtcTime;
3607 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
3608 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3609 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
3610 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3611 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3612 encodeFunc = CRYPT_AsnEncodeEnumerated;
3613 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3614 encodeFunc = CRYPT_AsnEncodeBits;
3615 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3616 encodeFunc = CRYPT_AsnEncodeOctets;
3617 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3618 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3619 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3620 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3621 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3622 encodeFunc = CRYPT_AsnEncodeAltName;
3623 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3624 encodeFunc = CRYPT_AsnEncodeAltName;
3625 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3626 encodeFunc = CRYPT_AsnEncodeAltName;
3627 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3628 encodeFunc = CRYPT_AsnEncodeAltName;
3629 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3630 encodeFunc = CRYPT_AsnEncodeAltName;
3631 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3632 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3633 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3634 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3635 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3636 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3637 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
3638 encodeFunc = CRYPT_AsnEncodeNameConstraints;
3639 return encodeFunc;
3642 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType,
3643 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
3645 static HCRYPTOIDFUNCSET set = NULL;
3646 CryptEncodeObjectFunc encodeFunc = NULL;
3648 if (!set)
3649 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
3650 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3651 (void **)&encodeFunc, hFunc);
3652 return encodeFunc;
3655 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType,
3656 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
3658 static HCRYPTOIDFUNCSET set = NULL;
3659 CryptEncodeObjectExFunc encodeFunc = NULL;
3661 if (!set)
3662 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
3663 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3664 (void **)&encodeFunc, hFunc);
3665 return encodeFunc;
3668 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3669 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
3671 BOOL ret = FALSE;
3672 HCRYPTOIDFUNCADDR hFunc = NULL;
3673 CryptEncodeObjectFunc pCryptEncodeObject = NULL;
3674 CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL;
3676 TRACE_(crypt)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
3677 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
3678 pcbEncoded);
3680 if (!pbEncoded && !pcbEncoded)
3682 SetLastError(ERROR_INVALID_PARAMETER);
3683 return FALSE;
3686 if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType,
3687 lpszStructType)))
3689 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
3690 debugstr_a(lpszStructType));
3691 pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType,
3692 lpszStructType, &hFunc);
3693 if (!pCryptEncodeObject)
3694 pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType,
3695 lpszStructType, &hFunc);
3697 if (pCryptEncodeObject)
3698 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3699 pvStructInfo, pbEncoded, pcbEncoded);
3700 else if (pCryptEncodeObjectEx)
3701 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
3702 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
3703 if (hFunc)
3704 CryptFreeOIDFunctionAddress(hFunc, 0);
3705 TRACE_(crypt)("returning %d\n", ret);
3706 return ret;
3709 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3710 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
3711 void *pvEncoded, DWORD *pcbEncoded)
3713 BOOL ret = FALSE;
3714 HCRYPTOIDFUNCADDR hFunc = NULL;
3715 CryptEncodeObjectExFunc encodeFunc = NULL;
3717 TRACE_(crypt)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
3718 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
3719 pvEncoded, pcbEncoded);
3721 if (!pvEncoded && !pcbEncoded)
3723 SetLastError(ERROR_INVALID_PARAMETER);
3724 return FALSE;
3727 SetLastError(NOERROR);
3728 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
3729 *(BYTE **)pvEncoded = NULL;
3730 encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType);
3731 if (!encodeFunc)
3733 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
3734 debugstr_a(lpszStructType));
3735 encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType,
3736 &hFunc);
3738 if (encodeFunc)
3739 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
3740 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
3741 else
3743 CryptEncodeObjectFunc pCryptEncodeObject =
3744 CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
3746 if (pCryptEncodeObject)
3748 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3750 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3751 pvStructInfo, NULL, pcbEncoded);
3752 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3753 pvEncoded, pcbEncoded, *pcbEncoded)))
3754 ret = pCryptEncodeObject(dwCertEncodingType,
3755 lpszStructType, pvStructInfo, *(BYTE **)pvEncoded,
3756 pcbEncoded);
3758 else
3759 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3760 pvStructInfo, pvEncoded, pcbEncoded);
3763 if (hFunc)
3764 CryptFreeOIDFunctionAddress(hFunc, 0);
3765 TRACE_(crypt)("returning %d\n", ret);
3766 return ret;
3769 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
3770 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3772 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
3773 NULL, 0, NULL, pInfo, pcbInfo);
3776 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
3777 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3778 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3780 BOOL ret;
3781 HCRYPTKEY key;
3782 static CHAR oid[] = szOID_RSA_RSA;
3784 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
3785 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
3786 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
3788 if (!pszPublicKeyObjId)
3789 pszPublicKeyObjId = oid;
3790 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
3792 DWORD keySize = 0;
3794 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
3795 if (ret)
3797 LPBYTE pubKey = CryptMemAlloc(keySize);
3799 if (pubKey)
3801 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
3802 &keySize);
3803 if (ret)
3805 DWORD encodedLen = 0;
3807 ret = CryptEncodeObject(dwCertEncodingType,
3808 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
3809 if (ret)
3811 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
3812 strlen(pszPublicKeyObjId) + 1 + encodedLen;
3814 if (!pInfo)
3815 *pcbInfo = sizeNeeded;
3816 else if (*pcbInfo < sizeNeeded)
3818 SetLastError(ERROR_MORE_DATA);
3819 *pcbInfo = sizeNeeded;
3820 ret = FALSE;
3822 else
3824 pInfo->Algorithm.pszObjId = (char *)pInfo +
3825 sizeof(CERT_PUBLIC_KEY_INFO);
3826 lstrcpyA(pInfo->Algorithm.pszObjId,
3827 pszPublicKeyObjId);
3828 pInfo->Algorithm.Parameters.cbData = 0;
3829 pInfo->Algorithm.Parameters.pbData = NULL;
3830 pInfo->PublicKey.pbData =
3831 (BYTE *)pInfo->Algorithm.pszObjId
3832 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
3833 pInfo->PublicKey.cbData = encodedLen;
3834 pInfo->PublicKey.cUnusedBits = 0;
3835 ret = CryptEncodeObject(dwCertEncodingType,
3836 RSA_CSP_PUBLICKEYBLOB, pubKey,
3837 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
3841 CryptMemFree(pubKey);
3843 else
3844 ret = FALSE;
3846 CryptDestroyKey(key);
3848 return ret;
3851 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
3852 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3853 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
3855 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
3856 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
3857 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3859 static HCRYPTOIDFUNCSET set = NULL;
3860 BOOL ret;
3861 ExportPublicKeyInfoExFunc exportFunc = NULL;
3862 HCRYPTOIDFUNCADDR hFunc = NULL;
3864 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
3865 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
3866 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
3868 if (!hCryptProv)
3870 SetLastError(ERROR_INVALID_PARAMETER);
3871 return FALSE;
3874 if (pszPublicKeyObjId)
3876 if (!set)
3877 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
3879 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
3880 0, (void **)&exportFunc, &hFunc);
3882 if (!exportFunc)
3883 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
3884 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
3885 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
3886 if (hFunc)
3887 CryptFreeOIDFunctionAddress(hFunc, 0);
3888 return ret;
3891 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
3892 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
3894 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
3895 0, 0, NULL, phKey);
3898 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3899 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3900 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3902 BOOL ret;
3903 DWORD pubKeySize = 0;
3905 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
3906 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3908 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3909 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
3910 if (ret)
3912 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
3914 if (pubKey)
3916 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3917 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
3918 &pubKeySize);
3919 if (ret)
3920 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
3921 phKey);
3922 CryptMemFree(pubKey);
3924 else
3925 ret = FALSE;
3927 return ret;
3930 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
3931 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3932 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
3934 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3935 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3936 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3938 static HCRYPTOIDFUNCSET set = NULL;
3939 BOOL ret;
3940 ImportPublicKeyInfoExFunc importFunc = NULL;
3941 HCRYPTOIDFUNCADDR hFunc = NULL;
3943 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
3944 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3946 if (!set)
3947 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
3948 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
3949 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
3950 if (!importFunc)
3951 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
3952 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
3953 pvAuxInfo, phKey);
3954 if (hFunc)
3955 CryptFreeOIDFunctionAddress(hFunc, 0);
3956 return ret;