crypt32: Partially implement encoding signed messages.
[wine.git] / dlls / crypt32 / encode.c
blobd63b38971184015d2c29c99544db2b0b66c45ecc
1 /*
2 * Copyright 2005 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER encoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface is
21 * undocumented, so I implement them here.
23 * References:
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially:
31 * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp
34 #include <assert.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <stdlib.h>
39 #define NONAMELESSUNION
41 #include "windef.h"
42 #include "winbase.h"
43 #include "wincrypt.h"
44 #include "snmp.h"
45 #include "wine/debug.h"
46 #include "wine/exception.h"
47 #include "wine/unicode.h"
48 #include "crypt32_private.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
52 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
53 BYTE *, DWORD *);
55 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
56 * The dwCertEncodingType and lpszStructType are ignored by the built-in
57 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
58 * since it must call functions in external DLLs that follow these signatures.
60 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
61 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
62 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
63 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
64 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
65 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
66 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
67 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
68 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
69 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
70 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
71 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
72 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
73 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
74 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
75 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
76 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
77 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
78 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
79 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
80 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
81 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
82 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
83 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
84 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
85 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
86 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
87 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
88 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
89 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
90 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
91 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
92 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
94 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
95 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
97 static HCRYPTOIDFUNCSET set = NULL;
98 BOOL ret = FALSE;
99 HCRYPTOIDFUNCADDR hFunc;
100 CryptEncodeObjectFunc pCryptEncodeObject;
102 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
103 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
104 pcbEncoded);
106 if (!pbEncoded && !pcbEncoded)
108 SetLastError(ERROR_INVALID_PARAMETER);
109 return FALSE;
112 /* Try registered DLL first.. */
113 if (!set)
114 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
115 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
116 (void **)&pCryptEncodeObject, &hFunc);
117 if (pCryptEncodeObject)
119 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
120 pvStructInfo, pbEncoded, pcbEncoded);
121 CryptFreeOIDFunctionAddress(hFunc, 0);
123 else
125 /* If not, use CryptEncodeObjectEx */
126 ret = CryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
127 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
129 return ret;
132 BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
133 BYTE *pbEncoded, DWORD *pcbEncoded, DWORD bytesNeeded)
135 BOOL ret = TRUE;
137 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
139 if (pEncodePara && pEncodePara->pfnAlloc)
140 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
141 else
142 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
143 if (!*(BYTE **)pbEncoded)
144 ret = FALSE;
145 else
146 *pcbEncoded = bytesNeeded;
148 else if (bytesNeeded > *pcbEncoded)
150 *pcbEncoded = bytesNeeded;
151 SetLastError(ERROR_MORE_DATA);
152 ret = FALSE;
154 else
155 *pcbEncoded = bytesNeeded;
156 return ret;
159 BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
161 DWORD bytesNeeded, significantBytes = 0;
163 if (len <= 0x7f)
164 bytesNeeded = 1;
165 else
167 DWORD temp;
169 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
170 temp <<= 8, significantBytes--)
172 bytesNeeded = significantBytes + 1;
174 if (!pbEncoded)
176 *pcbEncoded = bytesNeeded;
177 return TRUE;
179 if (*pcbEncoded < bytesNeeded)
181 SetLastError(ERROR_MORE_DATA);
182 return FALSE;
184 if (len <= 0x7f)
185 *pbEncoded = (BYTE)len;
186 else
188 DWORD i;
190 *pbEncoded++ = significantBytes | 0x80;
191 for (i = 0; i < significantBytes; i++)
193 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
194 len >>= 8;
197 *pcbEncoded = bytesNeeded;
198 return TRUE;
201 BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
202 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
203 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
205 BOOL ret;
206 DWORD i, dataLen = 0;
208 TRACE("%p, %d, %08x, %p, %p, %d\n", items, cItem, dwFlags, pEncodePara,
209 pbEncoded, *pcbEncoded);
210 for (i = 0, ret = TRUE; ret && i < cItem; i++)
212 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
213 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
214 NULL, &items[i].size);
215 /* Some functions propagate their errors through the size */
216 if (!ret)
217 *pcbEncoded = items[i].size;
218 dataLen += items[i].size;
220 if (ret)
222 DWORD lenBytes, bytesNeeded;
224 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
225 bytesNeeded = 1 + lenBytes + dataLen;
226 if (!pbEncoded)
227 *pcbEncoded = bytesNeeded;
228 else
230 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
231 pcbEncoded, bytesNeeded)))
233 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
234 pbEncoded = *(BYTE **)pbEncoded;
235 *pbEncoded++ = ASN_SEQUENCE;
236 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
237 pbEncoded += lenBytes;
238 for (i = 0; ret && i < cItem; i++)
240 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
241 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
242 NULL, pbEncoded, &items[i].size);
243 /* Some functions propagate their errors through the size */
244 if (!ret)
245 *pcbEncoded = items[i].size;
246 pbEncoded += items[i].size;
251 TRACE("returning %d (%08x)\n", ret, GetLastError());
252 return ret;
255 BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
256 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
257 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
259 BOOL ret;
260 const struct AsnConstructedItem *item =
261 (const struct AsnConstructedItem *)pvStructInfo;
262 DWORD len;
264 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
265 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
267 DWORD dataLen, bytesNeeded;
269 CRYPT_EncodeLen(len, NULL, &dataLen);
270 bytesNeeded = 1 + dataLen + len;
271 if (!pbEncoded)
272 *pcbEncoded = bytesNeeded;
273 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
274 pbEncoded, pcbEncoded, bytesNeeded)))
276 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
277 pbEncoded = *(BYTE **)pbEncoded;
278 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
279 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
280 pbEncoded += dataLen;
281 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
282 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
283 pbEncoded, &len);
284 if (!ret)
286 /* Some functions propagate their errors through the size */
287 *pcbEncoded = len;
291 else
293 /* Some functions propagate their errors through the size */
294 *pcbEncoded = len;
296 return ret;
299 struct AsnEncodeTagSwappedItem
301 BYTE tag;
302 const void *pvStructInfo;
303 CryptEncodeObjectExFunc encodeFunc;
306 /* Sort of a wacky hack, it encodes something using the struct
307 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
308 * given in the struct AsnEncodeTagSwappedItem.
310 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
311 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
312 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
314 BOOL ret;
315 const struct AsnEncodeTagSwappedItem *item =
316 (const struct AsnEncodeTagSwappedItem *)pvStructInfo;
318 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
319 item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
320 if (ret && pbEncoded)
321 *pbEncoded = item->tag;
322 return ret;
325 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
326 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
327 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
329 const DWORD *ver = (const DWORD *)pvStructInfo;
330 BOOL ret;
332 /* CERT_V1 is not encoded */
333 if (*ver == CERT_V1)
335 *pcbEncoded = 0;
336 ret = TRUE;
338 else
340 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
342 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
343 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
345 return ret;
348 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
349 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
350 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
352 const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
353 BOOL ret;
355 if (!pbEncoded)
357 *pcbEncoded = blob->cbData;
358 ret = TRUE;
360 else
362 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
363 pcbEncoded, blob->cbData)))
365 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
366 pbEncoded = *(BYTE **)pbEncoded;
367 if (blob->cbData)
368 memcpy(pbEncoded, blob->pbData, blob->cbData);
369 *pcbEncoded = blob->cbData;
370 ret = TRUE;
373 return ret;
376 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
377 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
378 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
380 BOOL ret;
381 /* This has two filetimes in a row, a NotBefore and a NotAfter */
382 const FILETIME *timePtr = (const FILETIME *)pvStructInfo;
383 struct AsnEncodeSequenceItem items[] = {
384 { timePtr++, CRYPT_AsnEncodeChoiceOfTime, 0 },
385 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
388 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
389 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
390 pcbEncoded);
391 return ret;
394 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
395 * if they are empty.
397 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
398 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
399 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
400 DWORD *pcbEncoded)
402 const CRYPT_ALGORITHM_IDENTIFIER *algo =
403 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
404 static const BYTE asn1Null[] = { ASN_NULL, 0 };
405 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
406 (LPBYTE)asn1Null };
407 BOOL ret;
408 struct AsnEncodeSequenceItem items[2] = {
409 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
410 { NULL, CRYPT_CopyEncodedBlob, 0 },
413 if (algo->Parameters.cbData)
414 items[1].pvStructInfo = &algo->Parameters;
415 else
416 items[1].pvStructInfo = &nullBlob;
417 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
418 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
419 pcbEncoded);
420 return ret;
423 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType,
424 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
425 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
427 const CRYPT_ALGORITHM_IDENTIFIER *algo =
428 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
429 BOOL ret;
430 struct AsnEncodeSequenceItem items[] = {
431 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
432 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
435 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
436 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
437 pcbEncoded);
438 return ret;
441 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
442 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
443 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
445 BOOL ret;
447 __TRY
449 const CERT_PUBLIC_KEY_INFO *info =
450 (const CERT_PUBLIC_KEY_INFO *)pvStructInfo;
451 struct AsnEncodeSequenceItem items[] = {
452 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
453 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
456 TRACE("Encoding public key with OID %s\n",
457 debugstr_a(info->Algorithm.pszObjId));
458 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
459 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
460 pcbEncoded);
462 __EXCEPT_PAGE_FAULT
464 SetLastError(STATUS_ACCESS_VIOLATION);
465 ret = FALSE;
467 __ENDTRY
468 return ret;
471 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
472 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
473 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
475 BOOL ret;
477 __TRY
479 const CERT_SIGNED_CONTENT_INFO *info =
480 (const CERT_SIGNED_CONTENT_INFO *)pvStructInfo;
481 struct AsnEncodeSequenceItem items[] = {
482 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
483 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
484 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
487 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
488 items[2].encodeFunc = CRYPT_AsnEncodeBits;
489 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
490 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
491 pcbEncoded);
493 __EXCEPT_PAGE_FAULT
495 SetLastError(STATUS_ACCESS_VIOLATION);
496 ret = FALSE;
498 __ENDTRY
499 return ret;
502 /* Like in Windows, this blithely ignores the validity of the passed-in
503 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
504 * decode properly, see CRYPT_AsnDecodeCertInfo.
506 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
507 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
508 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
510 BOOL ret;
512 __TRY
514 const CERT_INFO *info = (const CERT_INFO *)pvStructInfo;
515 struct AsnEncodeSequenceItem items[10] = {
516 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
517 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
518 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
519 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
520 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
521 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
522 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfo, 0 },
523 { 0 }
525 struct AsnConstructedItem constructed[3] = { { 0 } };
526 DWORD cItem = 7, cConstructed = 0;
528 if (info->IssuerUniqueId.cbData)
530 constructed[cConstructed].tag = 1;
531 constructed[cConstructed].pvStructInfo = &info->IssuerUniqueId;
532 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
533 items[cItem].pvStructInfo = &constructed[cConstructed];
534 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
535 cConstructed++;
536 cItem++;
538 if (info->SubjectUniqueId.cbData)
540 constructed[cConstructed].tag = 2;
541 constructed[cConstructed].pvStructInfo = &info->SubjectUniqueId;
542 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
543 items[cItem].pvStructInfo = &constructed[cConstructed];
544 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
545 cConstructed++;
546 cItem++;
548 if (info->cExtension)
550 constructed[cConstructed].tag = 3;
551 constructed[cConstructed].pvStructInfo = &info->cExtension;
552 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
553 items[cItem].pvStructInfo = &constructed[cConstructed];
554 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
555 cConstructed++;
556 cItem++;
559 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
560 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
562 __EXCEPT_PAGE_FAULT
564 SetLastError(STATUS_ACCESS_VIOLATION);
565 ret = FALSE;
567 __ENDTRY
568 return ret;
571 static BOOL WINAPI CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
572 BYTE *pbEncoded, DWORD *pcbEncoded)
574 struct AsnEncodeSequenceItem items[3] = {
575 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
576 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
577 { 0 }
579 DWORD cItem = 2;
580 BOOL ret;
582 TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded);
584 if (entry->cExtension)
586 items[cItem].pvStructInfo = &entry->cExtension;
587 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
588 cItem++;
591 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
592 pbEncoded, pcbEncoded);
594 TRACE("returning %d (%08x)\n", ret, GetLastError());
595 return ret;
598 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
599 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
600 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
602 DWORD cCRLEntry = *(const DWORD *)pvStructInfo;
603 DWORD bytesNeeded, dataLen, lenBytes, i;
604 const CRL_ENTRY *rgCRLEntry = *(const CRL_ENTRY *const *)
605 ((const BYTE *)pvStructInfo + sizeof(DWORD));
606 BOOL ret = TRUE;
608 for (i = 0, dataLen = 0; ret && i < cCRLEntry; i++)
610 DWORD size;
612 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
613 if (ret)
614 dataLen += size;
616 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
617 bytesNeeded = 1 + lenBytes + dataLen;
618 if (!pbEncoded)
619 *pcbEncoded = bytesNeeded;
620 else
622 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
623 pcbEncoded, bytesNeeded)))
625 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
626 pbEncoded = *(BYTE **)pbEncoded;
627 *pbEncoded++ = ASN_SEQUENCEOF;
628 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
629 pbEncoded += lenBytes;
630 for (i = 0; i < cCRLEntry; i++)
632 DWORD size = dataLen;
634 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], pbEncoded, &size);
635 pbEncoded += size;
636 dataLen -= size;
640 return ret;
643 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
644 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
645 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
647 const DWORD *ver = (const DWORD *)pvStructInfo;
648 BOOL ret;
650 /* CRL_V1 is not encoded */
651 if (*ver == CRL_V1)
653 *pcbEncoded = 0;
654 ret = TRUE;
656 else
657 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
658 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
659 return ret;
662 /* Like in Windows, this blithely ignores the validity of the passed-in
663 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
664 * decode properly, see CRYPT_AsnDecodeCRLInfo.
666 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
667 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
668 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
670 BOOL ret;
672 __TRY
674 const CRL_INFO *info = (const CRL_INFO *)pvStructInfo;
675 struct AsnEncodeSequenceItem items[7] = {
676 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
677 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
678 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
679 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
680 { 0 }
682 struct AsnConstructedItem constructed[1] = { { 0 } };
683 DWORD cItem = 4, cConstructed = 0;
685 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
687 items[cItem].pvStructInfo = &info->NextUpdate;
688 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
689 cItem++;
691 if (info->cCRLEntry)
693 items[cItem].pvStructInfo = &info->cCRLEntry;
694 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
695 cItem++;
697 if (info->cExtension)
699 constructed[cConstructed].tag = 0;
700 constructed[cConstructed].pvStructInfo = &info->cExtension;
701 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
702 items[cItem].pvStructInfo = &constructed[cConstructed];
703 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
704 cConstructed++;
705 cItem++;
708 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
709 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
711 __EXCEPT_PAGE_FAULT
713 SetLastError(STATUS_ACCESS_VIOLATION);
714 ret = FALSE;
716 __ENDTRY
717 return ret;
720 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
721 DWORD *pcbEncoded)
723 BOOL ret;
724 struct AsnEncodeSequenceItem items[3] = {
725 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
726 { NULL, NULL, 0 },
727 { NULL, NULL, 0 },
729 DWORD cItem = 1;
731 TRACE("%p, %p, %d\n", ext, pbEncoded, *pcbEncoded);
733 if (ext->fCritical)
735 items[cItem].pvStructInfo = &ext->fCritical;
736 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
737 cItem++;
739 items[cItem].pvStructInfo = &ext->Value;
740 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
741 cItem++;
743 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
744 pbEncoded, pcbEncoded);
745 TRACE("returning %d (%08x)\n", ret, GetLastError());
746 return ret;
749 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
750 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
751 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
753 BOOL ret;
755 __TRY
757 DWORD bytesNeeded, dataLen, lenBytes, i;
758 const CERT_EXTENSIONS *exts = (const CERT_EXTENSIONS *)pvStructInfo;
760 ret = TRUE;
761 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
763 DWORD size;
765 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
766 if (ret)
767 dataLen += size;
769 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
770 bytesNeeded = 1 + lenBytes + dataLen;
771 if (!pbEncoded)
772 *pcbEncoded = bytesNeeded;
773 else
775 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
776 pcbEncoded, bytesNeeded)))
778 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
779 pbEncoded = *(BYTE **)pbEncoded;
780 *pbEncoded++ = ASN_SEQUENCEOF;
781 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
782 pbEncoded += lenBytes;
783 for (i = 0; i < exts->cExtension; i++)
785 DWORD size = dataLen;
787 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
788 pbEncoded, &size);
789 pbEncoded += size;
790 dataLen -= size;
795 __EXCEPT_PAGE_FAULT
797 SetLastError(STATUS_ACCESS_VIOLATION);
798 ret = FALSE;
800 __ENDTRY
801 return ret;
804 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
805 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
806 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
808 LPCSTR pszObjId = (LPCSTR)pvStructInfo;
809 DWORD bytesNeeded = 0, lenBytes;
810 BOOL ret = TRUE;
811 int firstPos = 0;
812 BYTE firstByte = 0;
814 TRACE("%s\n", debugstr_a(pszObjId));
816 if (pszObjId)
818 const char *ptr;
819 int val1, val2;
821 if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
823 SetLastError(CRYPT_E_ASN1_ERROR);
824 return FALSE;
826 bytesNeeded++;
827 firstByte = val1 * 40 + val2;
828 ptr = pszObjId + firstPos;
829 while (ret && *ptr)
831 int pos;
833 /* note I assume each component is at most 32-bits long in base 2 */
834 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
836 if (val1 >= 0x10000000)
837 bytesNeeded += 5;
838 else if (val1 >= 0x200000)
839 bytesNeeded += 4;
840 else if (val1 >= 0x4000)
841 bytesNeeded += 3;
842 else if (val1 >= 0x80)
843 bytesNeeded += 2;
844 else
845 bytesNeeded += 1;
846 ptr += pos;
847 if (*ptr == '.')
848 ptr++;
850 else
852 SetLastError(CRYPT_E_ASN1_ERROR);
853 return FALSE;
856 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
858 else
859 lenBytes = 1;
860 bytesNeeded += 1 + lenBytes;
861 if (pbEncoded)
863 if (*pcbEncoded < bytesNeeded)
865 SetLastError(ERROR_MORE_DATA);
866 ret = FALSE;
868 else
870 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
871 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
872 pbEncoded += lenBytes;
873 if (pszObjId)
875 const char *ptr;
876 int val, pos;
878 *pbEncoded++ = firstByte;
879 ptr = pszObjId + firstPos;
880 while (ret && *ptr)
882 sscanf(ptr, "%d%n", &val, &pos);
884 unsigned char outBytes[5];
885 int numBytes, i;
887 if (val >= 0x10000000)
888 numBytes = 5;
889 else if (val >= 0x200000)
890 numBytes = 4;
891 else if (val >= 0x4000)
892 numBytes = 3;
893 else if (val >= 0x80)
894 numBytes = 2;
895 else
896 numBytes = 1;
897 for (i = numBytes; i > 0; i--)
899 outBytes[i - 1] = val & 0x7f;
900 val >>= 7;
902 for (i = 0; i < numBytes - 1; i++)
903 *pbEncoded++ = outBytes[i] | 0x80;
904 *pbEncoded++ = outBytes[i];
905 ptr += pos;
906 if (*ptr == '.')
907 ptr++;
913 *pcbEncoded = bytesNeeded;
914 return ret;
917 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
918 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
919 DWORD *pcbEncoded)
921 BOOL ret = TRUE;
922 LPCSTR str = (LPCSTR)value->Value.pbData;
923 DWORD bytesNeeded, lenBytes, encodedLen;
925 encodedLen = value->Value.cbData ? value->Value.cbData : lstrlenA(str);
926 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
927 bytesNeeded = 1 + lenBytes + encodedLen;
928 if (!pbEncoded)
929 *pcbEncoded = bytesNeeded;
930 else
932 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
933 pbEncoded, pcbEncoded, bytesNeeded)))
935 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
936 pbEncoded = *(BYTE **)pbEncoded;
937 *pbEncoded++ = tag;
938 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
939 pbEncoded += lenBytes;
940 memcpy(pbEncoded, str, encodedLen);
943 return ret;
946 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
947 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
948 DWORD *pcbEncoded)
950 BOOL ret = TRUE;
951 LPCWSTR str = (LPCWSTR)value->Value.pbData;
952 DWORD bytesNeeded, lenBytes, strLen;
954 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
955 lstrlenW(str);
956 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
957 bytesNeeded = 1 + lenBytes + strLen * 2;
958 if (!pbEncoded)
959 *pcbEncoded = bytesNeeded;
960 else
962 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
963 pbEncoded, pcbEncoded, bytesNeeded)))
965 DWORD i;
967 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
968 pbEncoded = *(BYTE **)pbEncoded;
969 *pbEncoded++ = ASN_BMPSTRING;
970 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
971 pbEncoded += lenBytes;
972 for (i = 0; i < strLen; i++)
974 *pbEncoded++ = (str[i] & 0xff00) >> 8;
975 *pbEncoded++ = str[i] & 0x00ff;
979 return ret;
982 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
983 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
984 DWORD *pcbEncoded)
986 BOOL ret = TRUE;
987 LPCWSTR str = (LPCWSTR)value->Value.pbData;
988 DWORD bytesNeeded, lenBytes, encodedLen, strLen;
990 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
991 lstrlenW(str);
992 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
993 NULL);
994 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
995 bytesNeeded = 1 + lenBytes + encodedLen;
996 if (!pbEncoded)
997 *pcbEncoded = bytesNeeded;
998 else
1000 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1001 pbEncoded, pcbEncoded, bytesNeeded)))
1003 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1004 pbEncoded = *(BYTE **)pbEncoded;
1005 *pbEncoded++ = ASN_UTF8STRING;
1006 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1007 pbEncoded += lenBytes;
1008 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
1009 bytesNeeded - lenBytes - 1, NULL, NULL);
1012 return ret;
1015 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
1016 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1017 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1019 BOOL ret = TRUE;
1021 __TRY
1023 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1025 switch (value->dwValueType)
1027 case CERT_RDN_ANY_TYPE:
1028 /* explicitly disallowed */
1029 SetLastError(E_INVALIDARG);
1030 ret = FALSE;
1031 break;
1032 case CERT_RDN_ENCODED_BLOB:
1033 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
1034 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1035 break;
1036 case CERT_RDN_OCTET_STRING:
1037 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1038 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1039 break;
1040 case CERT_RDN_NUMERIC_STRING:
1041 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1042 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1043 break;
1044 case CERT_RDN_PRINTABLE_STRING:
1045 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1046 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1047 break;
1048 case CERT_RDN_TELETEX_STRING:
1049 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1050 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1051 break;
1052 case CERT_RDN_VIDEOTEX_STRING:
1053 ret = CRYPT_AsnEncodeStringCoerce(value,
1054 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1055 break;
1056 case CERT_RDN_IA5_STRING:
1057 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1058 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1059 break;
1060 case CERT_RDN_GRAPHIC_STRING:
1061 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1062 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1063 break;
1064 case CERT_RDN_VISIBLE_STRING:
1065 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1066 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1067 break;
1068 case CERT_RDN_GENERAL_STRING:
1069 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1070 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1071 break;
1072 case CERT_RDN_UNIVERSAL_STRING:
1073 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1074 SetLastError(CRYPT_E_ASN1_CHOICE);
1075 ret = FALSE;
1076 break;
1077 case CERT_RDN_BMP_STRING:
1078 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1079 pbEncoded, pcbEncoded);
1080 break;
1081 case CERT_RDN_UTF8_STRING:
1082 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1083 pbEncoded, pcbEncoded);
1084 break;
1085 default:
1086 SetLastError(CRYPT_E_ASN1_CHOICE);
1087 ret = FALSE;
1090 __EXCEPT_PAGE_FAULT
1092 SetLastError(STATUS_ACCESS_VIOLATION);
1093 ret = FALSE;
1095 __ENDTRY
1096 return ret;
1099 static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1100 CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1101 BYTE *pbEncoded, DWORD *pcbEncoded)
1103 DWORD bytesNeeded = 0, lenBytes, size;
1104 BOOL ret;
1106 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1107 0, NULL, NULL, &size);
1108 if (ret)
1110 bytesNeeded += size;
1111 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1112 * with dwValueType, so "cast" it to get its encoded size
1114 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1115 (CERT_NAME_VALUE *)&attr->dwValueType, 0, NULL, NULL, &size);
1116 if (ret)
1118 bytesNeeded += size;
1119 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1120 bytesNeeded += 1 + lenBytes;
1121 if (pbEncoded)
1123 if (*pcbEncoded < bytesNeeded)
1125 SetLastError(ERROR_MORE_DATA);
1126 ret = FALSE;
1128 else
1130 *pbEncoded++ = ASN_SEQUENCE;
1131 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1132 &lenBytes);
1133 pbEncoded += lenBytes;
1134 size = bytesNeeded - 1 - lenBytes;
1135 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1136 attr->pszObjId, 0, NULL, pbEncoded, &size);
1137 if (ret)
1139 pbEncoded += size;
1140 size = bytesNeeded - 1 - lenBytes - size;
1141 ret = nameValueEncodeFunc(dwCertEncodingType,
1142 NULL, (CERT_NAME_VALUE *)&attr->dwValueType,
1143 0, NULL, pbEncoded, &size);
1144 if (!ret)
1145 *pcbEncoded = size;
1149 if (ret)
1150 *pcbEncoded = bytesNeeded;
1152 else
1154 /* Have to propagate index of failing character */
1155 *pcbEncoded = size;
1158 return ret;
1161 static int BLOBComp(const void *l, const void *r)
1163 const CRYPT_DER_BLOB *a = (const CRYPT_DER_BLOB *)l, *b = (const CRYPT_DER_BLOB *)r;
1164 int ret;
1166 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1167 ret = a->cbData - b->cbData;
1168 return ret;
1171 typedef struct _CRYPT_SET_OF {
1172 DWORD cValue;
1173 PCRYPT_DER_BLOB rgValue;
1174 } CRYPT_SET_OF;
1176 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1178 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1179 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1180 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1182 const CRYPT_SET_OF *set = (const CRYPT_SET_OF *)pvStructInfo;
1183 DWORD bytesNeeded = 0, lenBytes, i;
1184 BOOL ret;
1186 for (i = 0; i < set->cValue; i++)
1187 bytesNeeded += set->rgValue[i].cbData;
1188 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1189 bytesNeeded += 1 + lenBytes;
1190 if (!pbEncoded)
1192 *pcbEncoded = bytesNeeded;
1193 ret = TRUE;
1195 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1196 pbEncoded, pcbEncoded, bytesNeeded)))
1198 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1199 pbEncoded = *(BYTE **)pbEncoded;
1200 qsort(set->rgValue, set->cValue, sizeof(CRYPT_DER_BLOB), BLOBComp);
1201 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1202 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1203 pbEncoded += lenBytes;
1204 for (i = 0; ret && i < set->cValue; i++)
1206 memcpy(pbEncoded, set->rgValue[i].pbData, set->rgValue[i].cbData);
1207 pbEncoded += set->rgValue[i].cbData;
1210 return ret;
1213 struct DERSetDescriptor
1215 DWORD cItems;
1216 const void *items;
1217 size_t itemSize;
1218 off_t itemOffset;
1219 CryptEncodeObjectExFunc encode;
1222 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,
1223 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1224 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1226 const struct DERSetDescriptor *desc =
1227 (const struct DERSetDescriptor *)pvStructInfo;
1228 CRYPT_SET_OF setOf = { 0, NULL };
1229 BOOL ret = TRUE;
1230 DWORD i;
1232 if (desc->cItems)
1234 setOf.rgValue = CryptMemAlloc(setOf.cValue * sizeof(CRYPT_DER_BLOB));
1235 if (!setOf.rgValue)
1236 ret = FALSE;
1237 else
1239 setOf.cValue = desc->cItems;
1240 memset(setOf.rgValue, 0, setOf.cValue * sizeof(CRYPT_DER_BLOB));
1243 for (i = 0; ret && i < setOf.cValue; i++)
1245 ret = desc->encode(dwCertEncodingType, lpszStructType,
1246 (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
1247 0, NULL, NULL, &setOf.rgValue[i].cbData);
1248 if (ret)
1250 setOf.rgValue[i].pbData = CryptMemAlloc(setOf.rgValue[i].cbData);
1251 if (!setOf.rgValue[i].pbData)
1252 ret = FALSE;
1253 else
1254 ret = desc->encode(dwCertEncodingType, lpszStructType,
1255 (const BYTE *)desc->items + i * desc->itemSize +
1256 desc->itemOffset, 0, NULL, setOf.rgValue[i].pbData,
1257 &setOf.rgValue[i].cbData);
1259 /* Some functions propagate their errors through the size */
1260 if (!ret)
1261 *pcbEncoded = setOf.rgValue[i].cbData;
1263 if (ret)
1265 DWORD bytesNeeded = 0, lenBytes;
1266 BOOL ret;
1268 for (i = 0; i < setOf.cValue; i++)
1269 bytesNeeded += setOf.rgValue[i].cbData;
1270 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1271 bytesNeeded += 1 + lenBytes;
1272 if (!pbEncoded)
1273 *pcbEncoded = bytesNeeded;
1274 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1275 pbEncoded, pcbEncoded, bytesNeeded)))
1277 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1278 pbEncoded = *(BYTE **)pbEncoded;
1279 qsort(setOf.rgValue, setOf.cValue, sizeof(CRYPT_DER_BLOB),
1280 BLOBComp);
1281 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1282 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1283 pbEncoded += lenBytes;
1284 for (i = 0; i < setOf.cValue; i++)
1286 memcpy(pbEncoded, setOf.rgValue[i].pbData,
1287 setOf.rgValue[i].cbData);
1288 pbEncoded += setOf.rgValue[i].cbData;
1292 for (i = 0; i < setOf.cValue; i++)
1293 CryptMemFree(setOf.rgValue[i].pbData);
1294 CryptMemFree(setOf.rgValue);
1295 return ret;
1298 static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
1299 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1300 DWORD *pcbEncoded)
1302 BOOL ret;
1303 CRYPT_SET_OF setOf = { 0, NULL };
1305 __TRY
1307 DWORD i;
1309 ret = TRUE;
1310 if (rdn->cRDNAttr)
1312 setOf.cValue = rdn->cRDNAttr;
1313 setOf.rgValue = CryptMemAlloc(rdn->cRDNAttr *
1314 sizeof(CRYPT_DER_BLOB));
1315 if (!setOf.rgValue)
1316 ret = FALSE;
1317 else
1318 memset(setOf.rgValue, 0, setOf.cValue * sizeof(CRYPT_DER_BLOB));
1320 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1322 setOf.rgValue[i].cbData = 0;
1323 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1324 nameValueEncodeFunc, NULL, &setOf.rgValue[i].cbData);
1325 if (ret)
1327 setOf.rgValue[i].pbData =
1328 CryptMemAlloc(setOf.rgValue[i].cbData);
1329 if (!setOf.rgValue[i].pbData)
1330 ret = FALSE;
1331 else
1332 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1333 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1334 setOf.rgValue[i].pbData, &setOf.rgValue[i].cbData);
1336 if (!ret)
1338 /* Have to propagate index of failing character */
1339 *pcbEncoded = setOf.rgValue[i].cbData;
1342 if (ret)
1343 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1344 pbEncoded, pcbEncoded);
1345 for (i = 0; i < setOf.cValue; i++)
1346 CryptMemFree(setOf.rgValue[i].pbData);
1348 __EXCEPT_PAGE_FAULT
1350 SetLastError(STATUS_ACCESS_VIOLATION);
1351 ret = FALSE;
1353 __ENDTRY
1354 CryptMemFree(setOf.rgValue);
1355 return ret;
1358 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1359 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1360 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1362 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1363 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1364 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1365 DWORD *pcbEncoded)
1367 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1368 BOOL ret;
1370 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1371 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1372 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1373 else
1374 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1375 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1376 return ret;
1379 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1380 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1381 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1383 BOOL ret = TRUE;
1385 __TRY
1387 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1388 DWORD bytesNeeded = 0, lenBytes, size, i;
1390 TRACE("encoding name with %d RDNs\n", info->cRDN);
1391 ret = TRUE;
1392 for (i = 0; ret && i < info->cRDN; i++)
1394 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1395 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1396 if (ret)
1397 bytesNeeded += size;
1398 else
1399 *pcbEncoded = size;
1401 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1402 bytesNeeded += 1 + lenBytes;
1403 if (ret)
1405 if (!pbEncoded)
1406 *pcbEncoded = bytesNeeded;
1407 else
1409 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1410 pbEncoded, pcbEncoded, bytesNeeded)))
1412 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1413 pbEncoded = *(BYTE **)pbEncoded;
1414 *pbEncoded++ = ASN_SEQUENCEOF;
1415 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1416 &lenBytes);
1417 pbEncoded += lenBytes;
1418 for (i = 0; ret && i < info->cRDN; i++)
1420 size = bytesNeeded;
1421 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1422 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1423 pbEncoded, &size);
1424 if (ret)
1426 pbEncoded += size;
1427 bytesNeeded -= size;
1429 else
1430 *pcbEncoded = size;
1436 __EXCEPT_PAGE_FAULT
1438 SetLastError(STATUS_ACCESS_VIOLATION);
1439 ret = FALSE;
1441 __ENDTRY
1442 return ret;
1445 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1446 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1447 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1449 BOOL ret = FALSE;
1451 __TRY
1453 const CRYPT_ATTRIBUTE *attr = (const CRYPT_ATTRIBUTE *)pvStructInfo;
1455 if (!attr->pszObjId)
1456 SetLastError(E_INVALIDARG);
1457 else
1459 struct AsnEncodeSequenceItem items[2] = {
1460 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1461 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1464 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1465 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1466 pcbEncoded);
1469 __EXCEPT_PAGE_FAULT
1471 SetLastError(STATUS_ACCESS_VIOLATION);
1473 __ENDTRY
1474 return ret;
1477 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1478 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1479 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1481 BOOL ret = FALSE;
1483 __TRY
1485 const CRYPT_ATTRIBUTES *attributes =
1486 (const CRYPT_ATTRIBUTES *)pvStructInfo;
1487 struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
1488 sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
1490 ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
1491 &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1493 __EXCEPT_PAGE_FAULT
1495 SetLastError(STATUS_ACCESS_VIOLATION);
1497 __ENDTRY
1498 return ret;
1501 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1502 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
1503 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1504 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1505 DWORD *pcbEncoded)
1507 const CRYPT_CONTENT_INFO *info = (const CRYPT_CONTENT_INFO *)pvStructInfo;
1508 struct AsnEncodeSequenceItem items[2] = {
1509 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1510 { NULL, NULL, 0 },
1512 struct AsnConstructedItem constructed = { 0 };
1513 DWORD cItem = 1;
1515 if (info->Content.cbData)
1517 constructed.tag = 0;
1518 constructed.pvStructInfo = &info->Content;
1519 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1520 items[cItem].pvStructInfo = &constructed;
1521 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1522 cItem++;
1524 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1525 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1528 BOOL CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA *digestedData,
1529 void *pvData, DWORD *pcbData)
1531 struct AsnEncodeSequenceItem items[] = {
1532 { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1533 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
1534 0 },
1535 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1536 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1539 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1540 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
1543 BOOL CRYPT_AsnEncodePKCSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
1544 DWORD *pcbData)
1546 struct AsnEncodeSequenceItem items[7] = {
1547 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
1549 CRYPT_SET_OF digestAlgorithmsSet = { 0, NULL }, signerSet = { 0, NULL };
1550 DWORD i, cItem = 1;
1551 BOOL ret = TRUE;
1553 if (signedInfo->cCertEncoded)
1554 FIXME("unimplemented for certs\n");
1555 if (signedInfo->cCrlEncoded)
1556 FIXME("unimplemented for CRLs\n");
1557 if (signedInfo->cAttrCertEncoded)
1558 FIXME("unimplemented for attr certs\n");
1559 if (signedInfo->cSignerInfo)
1561 digestAlgorithmsSet.cValue = signedInfo->cSignerInfo;
1562 digestAlgorithmsSet.rgValue =
1563 CryptMemAlloc(digestAlgorithmsSet.cValue * sizeof(CRYPT_DER_BLOB));
1564 if (digestAlgorithmsSet.rgValue)
1566 memset(digestAlgorithmsSet.rgValue, 0,
1567 digestAlgorithmsSet.cValue * sizeof(CRYPT_DER_BLOB));
1568 for (i = 0; ret && i < digestAlgorithmsSet.cValue; i++)
1569 ret = CRYPT_AsnEncodeAlgorithmIdWithNullParams(0, NULL,
1570 &signedInfo->rgSignerInfo[i].HashAlgorithm,
1571 CRYPT_ENCODE_ALLOC_FLAG, NULL,
1572 (BYTE *)&digestAlgorithmsSet.rgValue[i].pbData,
1573 &digestAlgorithmsSet.rgValue[i].cbData);
1575 else
1576 ret = FALSE;
1577 if (ret)
1579 items[cItem].pvStructInfo = &digestAlgorithmsSet;
1580 items[cItem].encodeFunc = CRYPT_DEREncodeSet;
1581 cItem++;
1584 items[cItem].pvStructInfo = &signedInfo->content;
1585 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal;
1586 cItem++;
1587 if (ret && signedInfo->cSignerInfo)
1589 signerSet.cValue = signedInfo->cSignerInfo;
1590 signerSet.rgValue =
1591 CryptMemAlloc(signerSet.cValue * sizeof(CRYPT_DER_BLOB));
1592 if (signerSet.rgValue)
1594 memset(signerSet.rgValue, 0,
1595 signerSet.cValue * sizeof(CRYPT_DER_BLOB));
1596 for (i = 0; ret && i < signerSet.cValue; i++)
1597 ret = CryptEncodeObjectEx(
1598 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS7_SIGNER_INFO,
1599 &signedInfo->rgSignerInfo[i], CRYPT_ENCODE_ALLOC_FLAG, NULL,
1600 &signerSet.rgValue[i].pbData, &signerSet.rgValue[i].cbData);
1602 else
1603 ret = FALSE;
1604 if (ret)
1606 items[cItem].pvStructInfo = &signerSet;
1607 items[cItem].encodeFunc = CRYPT_DEREncodeSet;
1608 cItem++;
1611 if (ret)
1612 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
1613 pvData, pcbData);
1615 for (i = 0; i < digestAlgorithmsSet.cValue; i++)
1616 LocalFree(digestAlgorithmsSet.rgValue[i].pbData);
1617 CryptMemFree(digestAlgorithmsSet.rgValue);
1618 for (i = 0; i < signerSet.cValue; i++)
1619 LocalFree(signerSet.rgValue[i].pbData);
1620 CryptMemFree(signerSet.rgValue);
1622 return ret;
1625 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1626 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1627 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1629 BOOL ret = FALSE;
1631 __TRY
1633 const CRYPT_CONTENT_INFO *info =
1634 (const CRYPT_CONTENT_INFO *)pvStructInfo;
1636 if (!info->pszObjId)
1637 SetLastError(E_INVALIDARG);
1638 else
1639 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
1640 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1641 pcbEncoded);
1643 __EXCEPT_PAGE_FAULT
1645 SetLastError(STATUS_ACCESS_VIOLATION);
1647 __ENDTRY
1648 return ret;
1651 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1652 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1653 DWORD *pcbEncoded)
1655 BOOL ret = TRUE;
1656 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1657 DWORD bytesNeeded, lenBytes, encodedLen;
1659 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1660 lstrlenW(str);
1661 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1662 bytesNeeded = 1 + lenBytes + encodedLen;
1663 if (!pbEncoded)
1664 *pcbEncoded = bytesNeeded;
1665 else
1667 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1668 pbEncoded, pcbEncoded, bytesNeeded)))
1670 DWORD i;
1672 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1673 pbEncoded = *(BYTE **)pbEncoded;
1674 *pbEncoded++ = tag;
1675 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1676 pbEncoded += lenBytes;
1677 for (i = 0; i < encodedLen; i++)
1678 *pbEncoded++ = (BYTE)str[i];
1681 return ret;
1684 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
1685 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1686 DWORD *pcbEncoded)
1688 BOOL ret = TRUE;
1689 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1690 DWORD bytesNeeded, lenBytes, encodedLen;
1692 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1693 lstrlenW(str);
1694 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1695 bytesNeeded = 1 + lenBytes + encodedLen;
1696 if (!pbEncoded)
1697 *pcbEncoded = bytesNeeded;
1698 else
1700 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1701 pbEncoded, pcbEncoded, bytesNeeded)))
1703 DWORD i;
1705 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1706 pbEncoded = *(BYTE **)pbEncoded;
1707 *pbEncoded++ = ASN_NUMERICSTRING;
1708 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1709 pbEncoded += lenBytes;
1710 for (i = 0; ret && i < encodedLen; i++)
1712 if (isdigitW(str[i]))
1713 *pbEncoded++ = (BYTE)str[i];
1714 else
1716 *pcbEncoded = i;
1717 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
1718 ret = FALSE;
1723 return ret;
1726 static inline int isprintableW(WCHAR wc)
1728 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
1729 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
1730 wc == '/' || wc == ':' || wc == '=' || wc == '?';
1733 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
1734 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1735 DWORD *pcbEncoded)
1737 BOOL ret = TRUE;
1738 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1739 DWORD bytesNeeded, lenBytes, encodedLen;
1741 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1742 lstrlenW(str);
1743 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1744 bytesNeeded = 1 + lenBytes + encodedLen;
1745 if (!pbEncoded)
1746 *pcbEncoded = bytesNeeded;
1747 else
1749 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1750 pbEncoded, pcbEncoded, bytesNeeded)))
1752 DWORD i;
1754 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1755 pbEncoded = *(BYTE **)pbEncoded;
1756 *pbEncoded++ = ASN_PRINTABLESTRING;
1757 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1758 pbEncoded += lenBytes;
1759 for (i = 0; ret && i < encodedLen; i++)
1761 if (isprintableW(str[i]))
1762 *pbEncoded++ = (BYTE)str[i];
1763 else
1765 *pcbEncoded = i;
1766 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
1767 ret = FALSE;
1772 return ret;
1775 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
1776 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1777 DWORD *pcbEncoded)
1779 BOOL ret = TRUE;
1780 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1781 DWORD bytesNeeded, lenBytes, encodedLen;
1783 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1784 lstrlenW(str);
1785 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1786 bytesNeeded = 1 + lenBytes + encodedLen;
1787 if (!pbEncoded)
1788 *pcbEncoded = bytesNeeded;
1789 else
1791 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1792 pbEncoded, pcbEncoded, bytesNeeded)))
1794 DWORD i;
1796 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1797 pbEncoded = *(BYTE **)pbEncoded;
1798 *pbEncoded++ = ASN_IA5STRING;
1799 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1800 pbEncoded += lenBytes;
1801 for (i = 0; ret && i < encodedLen; i++)
1803 if (str[i] <= 0x7f)
1804 *pbEncoded++ = (BYTE)str[i];
1805 else
1807 *pcbEncoded = i;
1808 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1809 ret = FALSE;
1814 return ret;
1817 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
1818 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1819 DWORD *pcbEncoded)
1821 BOOL ret = TRUE;
1822 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1823 DWORD bytesNeeded, lenBytes, strLen;
1825 /* FIXME: doesn't handle composite characters */
1826 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1827 lstrlenW(str);
1828 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
1829 bytesNeeded = 1 + lenBytes + strLen * 4;
1830 if (!pbEncoded)
1831 *pcbEncoded = bytesNeeded;
1832 else
1834 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1835 pbEncoded, pcbEncoded, bytesNeeded)))
1837 DWORD i;
1839 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1840 pbEncoded = *(BYTE **)pbEncoded;
1841 *pbEncoded++ = ASN_UNIVERSALSTRING;
1842 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
1843 pbEncoded += lenBytes;
1844 for (i = 0; i < strLen; i++)
1846 *pbEncoded++ = 0;
1847 *pbEncoded++ = 0;
1848 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
1849 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
1853 return ret;
1856 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1857 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1858 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1860 BOOL ret = FALSE;
1862 __TRY
1864 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1866 switch (value->dwValueType)
1868 case CERT_RDN_ANY_TYPE:
1869 case CERT_RDN_ENCODED_BLOB:
1870 case CERT_RDN_OCTET_STRING:
1871 SetLastError(CRYPT_E_NOT_CHAR_STRING);
1872 break;
1873 case CERT_RDN_NUMERIC_STRING:
1874 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
1875 pbEncoded, pcbEncoded);
1876 break;
1877 case CERT_RDN_PRINTABLE_STRING:
1878 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
1879 pbEncoded, pcbEncoded);
1880 break;
1881 case CERT_RDN_TELETEX_STRING:
1882 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
1883 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1884 break;
1885 case CERT_RDN_VIDEOTEX_STRING:
1886 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
1887 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1888 break;
1889 case CERT_RDN_IA5_STRING:
1890 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
1891 pbEncoded, pcbEncoded);
1892 break;
1893 case CERT_RDN_GRAPHIC_STRING:
1894 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
1895 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1896 break;
1897 case CERT_RDN_VISIBLE_STRING:
1898 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
1899 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1900 break;
1901 case CERT_RDN_GENERAL_STRING:
1902 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
1903 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1904 break;
1905 case CERT_RDN_UNIVERSAL_STRING:
1906 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
1907 pbEncoded, pcbEncoded);
1908 break;
1909 case CERT_RDN_BMP_STRING:
1910 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1911 pbEncoded, pcbEncoded);
1912 break;
1913 case CERT_RDN_UTF8_STRING:
1914 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1915 pbEncoded, pcbEncoded);
1916 break;
1917 default:
1918 SetLastError(CRYPT_E_ASN1_CHOICE);
1921 __EXCEPT_PAGE_FAULT
1923 SetLastError(STATUS_ACCESS_VIOLATION);
1925 __ENDTRY
1926 return ret;
1929 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
1930 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1931 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1933 BOOL ret;
1935 __TRY
1937 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1938 DWORD bytesNeeded = 0, lenBytes, size, i;
1940 TRACE("encoding name with %d RDNs\n", info->cRDN);
1941 ret = TRUE;
1942 for (i = 0; ret && i < info->cRDN; i++)
1944 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1945 CRYPT_AsnEncodeNameValue, NULL, &size);
1946 if (ret)
1947 bytesNeeded += size;
1949 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1950 bytesNeeded += 1 + lenBytes;
1951 if (ret)
1953 if (!pbEncoded)
1954 *pcbEncoded = bytesNeeded;
1955 else
1957 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1958 pbEncoded, pcbEncoded, bytesNeeded)))
1960 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1961 pbEncoded = *(BYTE **)pbEncoded;
1962 *pbEncoded++ = ASN_SEQUENCEOF;
1963 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1964 &lenBytes);
1965 pbEncoded += lenBytes;
1966 for (i = 0; ret && i < info->cRDN; i++)
1968 size = bytesNeeded;
1969 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1970 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, pbEncoded,
1971 &size);
1972 if (ret)
1974 pbEncoded += size;
1975 bytesNeeded -= size;
1982 __EXCEPT_PAGE_FAULT
1984 SetLastError(STATUS_ACCESS_VIOLATION);
1985 ret = FALSE;
1987 __ENDTRY
1988 return ret;
1991 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1992 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1993 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1995 BOOL val = *(const BOOL *)pvStructInfo, ret;
1997 TRACE("%d\n", val);
1999 if (!pbEncoded)
2001 *pcbEncoded = 3;
2002 ret = TRUE;
2004 else if (*pcbEncoded < 3)
2006 *pcbEncoded = 3;
2007 SetLastError(ERROR_MORE_DATA);
2008 ret = FALSE;
2010 else
2012 *pcbEncoded = 3;
2013 *pbEncoded++ = ASN_BOOL;
2014 *pbEncoded++ = 1;
2015 *pbEncoded++ = val ? 0xff : 0;
2016 ret = TRUE;
2018 TRACE("returning %d (%08x)\n", ret, GetLastError());
2019 return ret;
2022 static BOOL CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY *entry,
2023 BYTE *pbEncoded, DWORD *pcbEncoded)
2025 BOOL ret;
2026 DWORD dataLen;
2028 ret = TRUE;
2029 switch (entry->dwAltNameChoice)
2031 case CERT_ALT_NAME_RFC822_NAME:
2032 case CERT_ALT_NAME_DNS_NAME:
2033 case CERT_ALT_NAME_URL:
2034 if (entry->u.pwszURL)
2036 DWORD i;
2038 /* Not + 1: don't encode the NULL-terminator */
2039 dataLen = lstrlenW(entry->u.pwszURL);
2040 for (i = 0; ret && i < dataLen; i++)
2042 if (entry->u.pwszURL[i] > 0x7f)
2044 SetLastError(CRYPT_E_INVALID_IA5_STRING);
2045 ret = FALSE;
2046 *pcbEncoded = i;
2050 else
2051 dataLen = 0;
2052 break;
2053 case CERT_ALT_NAME_IP_ADDRESS:
2054 dataLen = entry->u.IPAddress.cbData;
2055 break;
2056 case CERT_ALT_NAME_REGISTERED_ID:
2057 /* FIXME: encode OID */
2058 case CERT_ALT_NAME_OTHER_NAME:
2059 case CERT_ALT_NAME_DIRECTORY_NAME:
2060 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
2061 return FALSE;
2062 default:
2063 SetLastError(E_INVALIDARG);
2064 return FALSE;
2066 if (ret)
2068 DWORD bytesNeeded, lenBytes;
2070 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2071 bytesNeeded = 1 + dataLen + lenBytes;
2072 if (!pbEncoded)
2073 *pcbEncoded = bytesNeeded;
2074 else if (*pcbEncoded < bytesNeeded)
2076 SetLastError(ERROR_MORE_DATA);
2077 *pcbEncoded = bytesNeeded;
2078 ret = FALSE;
2080 else
2082 *pbEncoded++ = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2083 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2084 pbEncoded += lenBytes;
2085 switch (entry->dwAltNameChoice)
2087 case CERT_ALT_NAME_RFC822_NAME:
2088 case CERT_ALT_NAME_DNS_NAME:
2089 case CERT_ALT_NAME_URL:
2091 DWORD i;
2093 for (i = 0; i < dataLen; i++)
2094 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
2095 break;
2097 case CERT_ALT_NAME_IP_ADDRESS:
2098 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
2099 break;
2101 if (ret)
2102 *pcbEncoded = bytesNeeded;
2105 TRACE("returning %d (%08x)\n", ret, GetLastError());
2106 return ret;
2109 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
2110 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2111 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2113 BOOL ret;
2115 __TRY
2117 const CERT_AUTHORITY_KEY_ID_INFO *info =
2118 (const CERT_AUTHORITY_KEY_ID_INFO *)pvStructInfo;
2119 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2120 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2121 struct AsnConstructedItem constructed = { 0 };
2122 DWORD cItem = 0, cSwapped = 0;
2124 if (info->KeyId.cbData)
2126 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2127 swapped[cSwapped].pvStructInfo = &info->KeyId;
2128 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2129 items[cItem].pvStructInfo = &swapped[cSwapped];
2130 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2131 cSwapped++;
2132 cItem++;
2134 if (info->CertIssuer.cbData)
2136 constructed.tag = 1;
2137 constructed.pvStructInfo = &info->CertIssuer;
2138 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2139 items[cItem].pvStructInfo = &constructed;
2140 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2141 cItem++;
2143 if (info->CertSerialNumber.cbData)
2145 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2146 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2147 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2148 items[cItem].pvStructInfo = &swapped[cSwapped];
2149 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2150 cSwapped++;
2151 cItem++;
2153 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2154 pEncodePara, pbEncoded, pcbEncoded);
2156 __EXCEPT_PAGE_FAULT
2158 SetLastError(STATUS_ACCESS_VIOLATION);
2159 ret = FALSE;
2161 __ENDTRY
2162 return ret;
2165 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2166 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2167 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2169 BOOL ret;
2171 __TRY
2173 const CERT_ALT_NAME_INFO *info =
2174 (const CERT_ALT_NAME_INFO *)pvStructInfo;
2175 DWORD bytesNeeded, dataLen, lenBytes, i;
2177 ret = TRUE;
2178 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2179 * can't encode an erroneous entry index if it's bigger than this.
2181 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2183 DWORD len;
2185 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i], NULL,
2186 &len);
2187 if (ret)
2188 dataLen += len;
2189 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2191 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2192 * the bad character, now set the index of the bad
2193 * entry
2195 *pcbEncoded = (BYTE)i <<
2196 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2199 if (ret)
2201 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2202 bytesNeeded = 1 + lenBytes + dataLen;
2203 if (!pbEncoded)
2205 *pcbEncoded = bytesNeeded;
2206 ret = TRUE;
2208 else
2210 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2211 pbEncoded, pcbEncoded, bytesNeeded)))
2213 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2214 pbEncoded = *(BYTE **)pbEncoded;
2215 *pbEncoded++ = ASN_SEQUENCEOF;
2216 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2217 pbEncoded += lenBytes;
2218 for (i = 0; ret && i < info->cAltEntry; i++)
2220 DWORD len = dataLen;
2222 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i],
2223 pbEncoded, &len);
2224 if (ret)
2226 pbEncoded += len;
2227 dataLen -= len;
2234 __EXCEPT_PAGE_FAULT
2236 SetLastError(STATUS_ACCESS_VIOLATION);
2237 ret = FALSE;
2239 __ENDTRY
2240 return ret;
2243 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2244 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2245 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2247 BOOL ret;
2249 __TRY
2251 const CERT_AUTHORITY_KEY_ID2_INFO *info =
2252 (const CERT_AUTHORITY_KEY_ID2_INFO *)pvStructInfo;
2253 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2254 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2255 DWORD cItem = 0, cSwapped = 0;
2257 if (info->KeyId.cbData)
2259 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2260 swapped[cSwapped].pvStructInfo = &info->KeyId;
2261 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2262 items[cItem].pvStructInfo = &swapped[cSwapped];
2263 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2264 cSwapped++;
2265 cItem++;
2267 if (info->AuthorityCertIssuer.cAltEntry)
2269 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2270 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2271 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2272 items[cItem].pvStructInfo = &swapped[cSwapped];
2273 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2274 cSwapped++;
2275 cItem++;
2277 if (info->AuthorityCertSerialNumber.cbData)
2279 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2280 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2281 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2282 items[cItem].pvStructInfo = &swapped[cSwapped];
2283 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2284 cSwapped++;
2285 cItem++;
2287 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2288 pEncodePara, pbEncoded, pcbEncoded);
2290 __EXCEPT_PAGE_FAULT
2292 SetLastError(STATUS_ACCESS_VIOLATION);
2293 ret = FALSE;
2295 __ENDTRY
2296 return ret;
2299 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2300 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2301 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2303 BOOL ret;
2305 __TRY
2307 const CERT_BASIC_CONSTRAINTS_INFO *info =
2308 (const CERT_BASIC_CONSTRAINTS_INFO *)pvStructInfo;
2309 struct AsnEncodeSequenceItem items[3] = {
2310 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2311 { 0 }
2313 DWORD cItem = 1;
2315 if (info->fPathLenConstraint)
2317 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2318 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2319 cItem++;
2321 if (info->cSubtreesConstraint)
2323 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2324 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2325 cItem++;
2327 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2328 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2330 __EXCEPT_PAGE_FAULT
2332 SetLastError(STATUS_ACCESS_VIOLATION);
2333 ret = FALSE;
2335 __ENDTRY
2336 return ret;
2339 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2340 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2341 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2343 BOOL ret;
2345 __TRY
2347 const CERT_BASIC_CONSTRAINTS2_INFO *info =
2348 (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
2349 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2350 DWORD cItem = 0;
2352 if (info->fCA)
2354 items[cItem].pvStructInfo = &info->fCA;
2355 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2356 cItem++;
2358 if (info->fPathLenConstraint)
2360 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2361 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2362 cItem++;
2364 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2365 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2367 __EXCEPT_PAGE_FAULT
2369 SetLastError(STATUS_ACCESS_VIOLATION);
2370 ret = FALSE;
2372 __ENDTRY
2373 return ret;
2376 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
2377 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2378 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2380 BOOL ret;
2382 __TRY
2384 const BLOBHEADER *hdr =
2385 (const BLOBHEADER *)pvStructInfo;
2387 if (hdr->bType != PUBLICKEYBLOB)
2389 SetLastError(E_INVALIDARG);
2390 ret = FALSE;
2392 else
2394 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
2395 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
2396 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
2397 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
2398 struct AsnEncodeSequenceItem items[] = {
2399 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
2400 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
2403 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2404 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
2405 pcbEncoded);
2408 __EXCEPT_PAGE_FAULT
2410 SetLastError(STATUS_ACCESS_VIOLATION);
2411 ret = FALSE;
2413 __ENDTRY
2414 return ret;
2417 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
2418 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2419 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2421 BOOL ret;
2423 __TRY
2425 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2426 DWORD bytesNeeded, lenBytes;
2428 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
2429 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
2431 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
2432 bytesNeeded = 1 + lenBytes + blob->cbData;
2433 if (!pbEncoded)
2435 *pcbEncoded = bytesNeeded;
2436 ret = TRUE;
2438 else
2440 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2441 pcbEncoded, bytesNeeded)))
2443 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2444 pbEncoded = *(BYTE **)pbEncoded;
2445 *pbEncoded++ = ASN_OCTETSTRING;
2446 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
2447 pbEncoded += lenBytes;
2448 if (blob->cbData)
2449 memcpy(pbEncoded, blob->pbData, blob->cbData);
2453 __EXCEPT_PAGE_FAULT
2455 SetLastError(STATUS_ACCESS_VIOLATION);
2456 ret = FALSE;
2458 __ENDTRY
2459 TRACE("returning %d (%08x)\n", ret, GetLastError());
2460 return ret;
2463 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
2464 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2465 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2467 BOOL ret;
2469 __TRY
2471 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2472 DWORD bytesNeeded, lenBytes, dataBytes;
2473 BYTE unusedBits;
2475 /* yep, MS allows cUnusedBits to be >= 8 */
2476 if (!blob->cUnusedBits)
2478 dataBytes = blob->cbData;
2479 unusedBits = 0;
2481 else if (blob->cbData * 8 > blob->cUnusedBits)
2483 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
2484 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
2485 blob->cUnusedBits;
2487 else
2489 dataBytes = 0;
2490 unusedBits = 0;
2492 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
2493 bytesNeeded = 1 + lenBytes + dataBytes + 1;
2494 if (!pbEncoded)
2496 *pcbEncoded = bytesNeeded;
2497 ret = TRUE;
2499 else
2501 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2502 pcbEncoded, bytesNeeded)))
2504 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2505 pbEncoded = *(BYTE **)pbEncoded;
2506 *pbEncoded++ = ASN_BITSTRING;
2507 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
2508 pbEncoded += lenBytes;
2509 *pbEncoded++ = unusedBits;
2510 if (dataBytes)
2512 BYTE mask = 0xff << unusedBits;
2514 if (dataBytes > 1)
2516 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
2517 pbEncoded += dataBytes - 1;
2519 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
2524 __EXCEPT_PAGE_FAULT
2526 SetLastError(STATUS_ACCESS_VIOLATION);
2527 ret = FALSE;
2529 __ENDTRY
2530 return ret;
2533 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(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 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2542 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
2544 ret = TRUE;
2545 if (newBlob.cbData)
2547 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2548 if (newBlob.pbData)
2550 DWORD i;
2552 for (i = 0; i < newBlob.cbData; i++)
2553 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2555 else
2556 ret = FALSE;
2558 if (ret)
2559 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
2560 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2561 CryptMemFree(newBlob.pbData);
2563 __EXCEPT_PAGE_FAULT
2565 SetLastError(STATUS_ACCESS_VIOLATION);
2566 ret = FALSE;
2568 __ENDTRY
2569 return ret;
2572 BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
2573 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2574 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2576 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
2578 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
2579 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2582 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
2583 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2584 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2586 BOOL ret;
2588 __TRY
2590 DWORD significantBytes, lenBytes;
2591 BYTE padByte = 0, bytesNeeded;
2592 BOOL pad = FALSE;
2593 const CRYPT_INTEGER_BLOB *blob =
2594 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2596 significantBytes = blob->cbData;
2597 if (significantBytes)
2599 if (blob->pbData[significantBytes - 1] & 0x80)
2601 /* negative, lop off leading (little-endian) 0xffs */
2602 for (; significantBytes > 0 &&
2603 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
2605 if (blob->pbData[significantBytes - 1] < 0x80)
2607 padByte = 0xff;
2608 pad = TRUE;
2611 else
2613 /* positive, lop off leading (little-endian) zeroes */
2614 for (; significantBytes > 0 &&
2615 !blob->pbData[significantBytes - 1]; significantBytes--)
2617 if (significantBytes == 0)
2618 significantBytes = 1;
2619 if (blob->pbData[significantBytes - 1] > 0x7f)
2621 padByte = 0;
2622 pad = TRUE;
2626 if (pad)
2627 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2628 else
2629 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2630 bytesNeeded = 1 + lenBytes + significantBytes;
2631 if (pad)
2632 bytesNeeded++;
2633 if (!pbEncoded)
2635 *pcbEncoded = bytesNeeded;
2636 ret = TRUE;
2638 else
2640 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2641 pcbEncoded, bytesNeeded)))
2643 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2644 pbEncoded = *(BYTE **)pbEncoded;
2645 *pbEncoded++ = ASN_INTEGER;
2646 if (pad)
2648 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2649 pbEncoded += lenBytes;
2650 *pbEncoded++ = padByte;
2652 else
2654 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2655 pbEncoded += lenBytes;
2657 for (; significantBytes > 0; significantBytes--)
2658 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2662 __EXCEPT_PAGE_FAULT
2664 SetLastError(STATUS_ACCESS_VIOLATION);
2665 ret = FALSE;
2667 __ENDTRY
2668 return ret;
2671 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
2672 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2673 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2675 BOOL ret;
2677 __TRY
2679 DWORD significantBytes, lenBytes;
2680 BYTE bytesNeeded;
2681 BOOL pad = FALSE;
2682 const CRYPT_INTEGER_BLOB *blob =
2683 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2685 significantBytes = blob->cbData;
2686 if (significantBytes)
2688 /* positive, lop off leading (little-endian) zeroes */
2689 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
2690 significantBytes--)
2692 if (significantBytes == 0)
2693 significantBytes = 1;
2694 if (blob->pbData[significantBytes - 1] > 0x7f)
2695 pad = TRUE;
2697 if (pad)
2698 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2699 else
2700 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2701 bytesNeeded = 1 + lenBytes + significantBytes;
2702 if (pad)
2703 bytesNeeded++;
2704 if (!pbEncoded)
2706 *pcbEncoded = bytesNeeded;
2707 ret = TRUE;
2709 else
2711 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2712 pcbEncoded, bytesNeeded)))
2714 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2715 pbEncoded = *(BYTE **)pbEncoded;
2716 *pbEncoded++ = ASN_INTEGER;
2717 if (pad)
2719 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2720 pbEncoded += lenBytes;
2721 *pbEncoded++ = 0;
2723 else
2725 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2726 pbEncoded += lenBytes;
2728 for (; significantBytes > 0; significantBytes--)
2729 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2733 __EXCEPT_PAGE_FAULT
2735 SetLastError(STATUS_ACCESS_VIOLATION);
2736 ret = FALSE;
2738 __ENDTRY
2739 return ret;
2742 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
2743 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2744 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2746 CRYPT_INTEGER_BLOB blob;
2747 BOOL ret;
2749 /* Encode as an unsigned integer, then change the tag to enumerated */
2750 blob.cbData = sizeof(DWORD);
2751 blob.pbData = (BYTE *)pvStructInfo;
2752 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
2753 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2754 if (ret && pbEncoded)
2756 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2757 pbEncoded = *(BYTE **)pbEncoded;
2758 pbEncoded[0] = ASN_ENUMERATED;
2760 return ret;
2763 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
2764 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2765 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2767 BOOL ret;
2769 __TRY
2771 SYSTEMTIME sysTime;
2772 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2773 * temporary buffer because the output buffer is not NULL-terminated.
2775 char buf[16];
2776 static const DWORD bytesNeeded = sizeof(buf) - 1;
2778 if (!pbEncoded)
2780 *pcbEncoded = bytesNeeded;
2781 ret = TRUE;
2783 else
2785 /* Sanity check the year, this is a two-digit year format */
2786 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2787 &sysTime);
2788 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
2790 SetLastError(CRYPT_E_BAD_ENCODE);
2791 ret = FALSE;
2793 if (ret)
2795 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2796 pbEncoded, pcbEncoded, bytesNeeded)))
2798 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2799 pbEncoded = *(BYTE **)pbEncoded;
2800 buf[0] = ASN_UTCTIME;
2801 buf[1] = bytesNeeded - 2;
2802 snprintf(buf + 2, sizeof(buf) - 2,
2803 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
2804 sysTime.wYear - 2000 : sysTime.wYear - 1900,
2805 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2806 sysTime.wMinute, sysTime.wSecond);
2807 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_AsnEncodeGeneralizedTime(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;
2830 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2831 * temporary buffer because the output buffer is not NULL-terminated.
2833 char buf[18];
2834 static const DWORD bytesNeeded = sizeof(buf) - 1;
2836 if (!pbEncoded)
2838 *pcbEncoded = bytesNeeded;
2839 ret = TRUE;
2841 else
2843 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2844 &sysTime);
2845 if (ret)
2846 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2847 pcbEncoded, bytesNeeded);
2848 if (ret)
2850 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2851 pbEncoded = *(BYTE **)pbEncoded;
2852 buf[0] = ASN_GENERALTIME;
2853 buf[1] = bytesNeeded - 2;
2854 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
2855 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2856 sysTime.wMinute, sysTime.wSecond);
2857 memcpy(pbEncoded, buf, bytesNeeded);
2861 __EXCEPT_PAGE_FAULT
2863 SetLastError(STATUS_ACCESS_VIOLATION);
2864 ret = FALSE;
2866 __ENDTRY
2867 return ret;
2870 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
2871 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2872 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2874 BOOL ret;
2876 __TRY
2878 SYSTEMTIME sysTime;
2880 /* Check the year, if it's in the UTCTime range call that encode func */
2881 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
2882 return FALSE;
2883 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
2884 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
2885 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2886 else
2887 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
2888 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
2889 pcbEncoded);
2891 __EXCEPT_PAGE_FAULT
2893 SetLastError(STATUS_ACCESS_VIOLATION);
2894 ret = FALSE;
2896 __ENDTRY
2897 return ret;
2900 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
2901 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2902 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2904 BOOL ret;
2906 __TRY
2908 DWORD bytesNeeded, dataLen, lenBytes, i;
2909 const CRYPT_SEQUENCE_OF_ANY *seq =
2910 (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2912 for (i = 0, dataLen = 0; i < seq->cValue; i++)
2913 dataLen += seq->rgValue[i].cbData;
2914 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2915 bytesNeeded = 1 + lenBytes + dataLen;
2916 if (!pbEncoded)
2918 *pcbEncoded = bytesNeeded;
2919 ret = TRUE;
2921 else
2923 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2924 pcbEncoded, bytesNeeded)))
2926 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2927 pbEncoded = *(BYTE **)pbEncoded;
2928 *pbEncoded++ = ASN_SEQUENCEOF;
2929 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2930 pbEncoded += lenBytes;
2931 for (i = 0; i < seq->cValue; i++)
2933 memcpy(pbEncoded, seq->rgValue[i].pbData,
2934 seq->rgValue[i].cbData);
2935 pbEncoded += seq->rgValue[i].cbData;
2940 __EXCEPT_PAGE_FAULT
2942 SetLastError(STATUS_ACCESS_VIOLATION);
2943 ret = FALSE;
2945 __ENDTRY
2946 return ret;
2949 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
2950 BYTE *pbEncoded, DWORD *pcbEncoded)
2952 BOOL ret = TRUE;
2953 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2954 struct AsnConstructedItem constructed = { 0 };
2955 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2956 DWORD cItem = 0, cSwapped = 0;
2958 switch (distPoint->DistPointName.dwDistPointNameChoice)
2960 case CRL_DIST_POINT_NO_NAME:
2961 /* do nothing */
2962 break;
2963 case CRL_DIST_POINT_FULL_NAME:
2964 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
2965 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
2966 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2967 constructed.tag = 0;
2968 constructed.pvStructInfo = &swapped[cSwapped];
2969 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
2970 items[cItem].pvStructInfo = &constructed;
2971 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2972 cSwapped++;
2973 cItem++;
2974 break;
2975 case CRL_DIST_POINT_ISSUER_RDN_NAME:
2976 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2977 ret = FALSE;
2978 break;
2979 default:
2980 ret = FALSE;
2982 if (ret && distPoint->ReasonFlags.cbData)
2984 swapped[cSwapped].tag = ASN_CONTEXT | 1;
2985 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
2986 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
2987 items[cItem].pvStructInfo = &swapped[cSwapped];
2988 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2989 cSwapped++;
2990 cItem++;
2992 if (ret && distPoint->CRLIssuer.cAltEntry)
2994 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
2995 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
2996 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2997 items[cItem].pvStructInfo = &swapped[cSwapped];
2998 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2999 cSwapped++;
3000 cItem++;
3002 if (ret)
3003 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
3004 pbEncoded, pcbEncoded);
3005 return ret;
3008 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
3009 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3010 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3012 BOOL ret;
3014 __TRY
3016 const CRL_DIST_POINTS_INFO *info =
3017 (const CRL_DIST_POINTS_INFO *)pvStructInfo;
3019 if (!info->cDistPoint)
3021 SetLastError(E_INVALIDARG);
3022 ret = FALSE;
3024 else
3026 DWORD bytesNeeded, dataLen, lenBytes, i;
3028 ret = TRUE;
3029 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
3031 DWORD len;
3033 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
3034 &len);
3035 if (ret)
3036 dataLen += len;
3037 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
3039 /* Have to propagate index of failing character */
3040 *pcbEncoded = len;
3043 if (ret)
3045 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3046 bytesNeeded = 1 + lenBytes + dataLen;
3047 if (!pbEncoded)
3049 *pcbEncoded = bytesNeeded;
3050 ret = TRUE;
3052 else
3054 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3055 pbEncoded, pcbEncoded, bytesNeeded)))
3057 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3058 pbEncoded = *(BYTE **)pbEncoded;
3059 *pbEncoded++ = ASN_SEQUENCEOF;
3060 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
3061 pbEncoded += lenBytes;
3062 for (i = 0; ret && i < info->cDistPoint; i++)
3064 DWORD len = dataLen;
3066 ret = CRYPT_AsnEncodeDistPoint(
3067 &info->rgDistPoint[i], pbEncoded, &len);
3068 if (ret)
3070 pbEncoded += len;
3071 dataLen -= len;
3079 __EXCEPT_PAGE_FAULT
3081 SetLastError(STATUS_ACCESS_VIOLATION);
3082 ret = FALSE;
3084 __ENDTRY
3085 return ret;
3088 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3089 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3090 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3092 BOOL ret;
3094 __TRY
3096 const CERT_ENHKEY_USAGE *usage =
3097 (const CERT_ENHKEY_USAGE *)pvStructInfo;
3098 DWORD bytesNeeded = 0, lenBytes, size, i;
3100 ret = TRUE;
3101 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3103 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3104 usage->rgpszUsageIdentifier[i],
3105 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
3106 if (ret)
3107 bytesNeeded += size;
3109 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3110 bytesNeeded += 1 + lenBytes;
3111 if (ret)
3113 if (!pbEncoded)
3114 *pcbEncoded = bytesNeeded;
3115 else
3117 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3118 pbEncoded, pcbEncoded, bytesNeeded)))
3120 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3121 pbEncoded = *(BYTE **)pbEncoded;
3122 *pbEncoded++ = ASN_SEQUENCEOF;
3123 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
3124 &lenBytes);
3125 pbEncoded += lenBytes;
3126 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3128 size = bytesNeeded;
3129 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3130 usage->rgpszUsageIdentifier[i],
3131 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
3132 &size);
3133 if (ret)
3135 pbEncoded += size;
3136 bytesNeeded -= size;
3143 __EXCEPT_PAGE_FAULT
3145 SetLastError(STATUS_ACCESS_VIOLATION);
3146 ret = FALSE;
3148 __ENDTRY
3149 return ret;
3152 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
3153 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3154 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3156 BOOL ret;
3158 __TRY
3160 const CRL_ISSUING_DIST_POINT *point =
3161 (const CRL_ISSUING_DIST_POINT *)pvStructInfo;
3162 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3163 struct AsnConstructedItem constructed = { 0 };
3164 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3165 DWORD cItem = 0, cSwapped = 0;
3167 ret = TRUE;
3168 switch (point->DistPointName.dwDistPointNameChoice)
3170 case CRL_DIST_POINT_NO_NAME:
3171 /* do nothing */
3172 break;
3173 case CRL_DIST_POINT_FULL_NAME:
3174 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3175 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3176 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3177 constructed.tag = 0;
3178 constructed.pvStructInfo = &swapped[cSwapped];
3179 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3180 items[cItem].pvStructInfo = &constructed;
3181 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3182 cSwapped++;
3183 cItem++;
3184 break;
3185 default:
3186 SetLastError(E_INVALIDARG);
3187 ret = FALSE;
3189 if (ret && point->fOnlyContainsUserCerts)
3191 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3192 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3193 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3194 items[cItem].pvStructInfo = &swapped[cSwapped];
3195 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3196 cSwapped++;
3197 cItem++;
3199 if (ret && point->fOnlyContainsCACerts)
3201 swapped[cSwapped].tag = ASN_CONTEXT | 2;
3202 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3203 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3204 items[cItem].pvStructInfo = &swapped[cSwapped];
3205 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3206 cSwapped++;
3207 cItem++;
3209 if (ret && point->OnlySomeReasonFlags.cbData)
3211 swapped[cSwapped].tag = ASN_CONTEXT | 3;
3212 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3213 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3214 items[cItem].pvStructInfo = &swapped[cSwapped];
3215 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3216 cSwapped++;
3217 cItem++;
3219 if (ret && point->fIndirectCRL)
3221 swapped[cSwapped].tag = ASN_CONTEXT | 4;
3222 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
3223 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3224 items[cItem].pvStructInfo = &swapped[cSwapped];
3225 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3226 cSwapped++;
3227 cItem++;
3229 if (ret)
3230 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3231 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3233 __EXCEPT_PAGE_FAULT
3235 SetLastError(STATUS_ACCESS_VIOLATION);
3236 ret = FALSE;
3238 __ENDTRY
3239 return ret;
3242 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
3243 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3244 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3245 DWORD *pcbEncoded)
3247 BOOL ret;
3248 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3249 (const CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3250 struct AsnEncodeSequenceItem items[] = {
3251 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
3252 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
3255 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3256 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3257 pcbEncoded);
3258 return ret;
3261 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
3262 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3263 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3265 BOOL ret = FALSE;
3267 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
3269 SetLastError(E_INVALIDARG);
3270 return FALSE;
3273 __TRY
3275 const CMSG_SIGNER_INFO *info = (const CMSG_SIGNER_INFO *)pvStructInfo;
3277 if (!info->Issuer.cbData)
3278 SetLastError(E_INVALIDARG);
3279 else
3281 struct AsnEncodeSequenceItem items[7] = {
3282 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
3283 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
3284 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
3285 0 },
3286 { &info->HashEncryptionAlgorithm,
3287 CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
3289 DWORD cItem = 4;
3291 if (info->AuthAttrs.cAttr)
3293 items[cItem].pvStructInfo = &info->AuthAttrs;
3294 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3295 cItem++;
3297 if (info->UnauthAttrs.cAttr)
3299 items[cItem].pvStructInfo = &info->UnauthAttrs;
3300 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3301 cItem++;
3303 items[cItem].pvStructInfo = &info->EncryptedHash;
3304 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
3305 cItem++;
3306 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3307 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3310 __EXCEPT_PAGE_FAULT
3312 SetLastError(STATUS_ACCESS_VIOLATION);
3314 __ENDTRY
3315 return ret;
3318 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3319 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
3320 void *pvEncoded, DWORD *pcbEncoded)
3322 static HCRYPTOIDFUNCSET set = NULL;
3323 BOOL ret = FALSE;
3324 CryptEncodeObjectExFunc encodeFunc = NULL;
3325 HCRYPTOIDFUNCADDR hFunc = NULL;
3327 TRACE("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
3328 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
3329 pvEncoded, pcbEncoded);
3331 if (!pvEncoded && !pcbEncoded)
3333 SetLastError(ERROR_INVALID_PARAMETER);
3334 return FALSE;
3336 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3337 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3339 SetLastError(ERROR_FILE_NOT_FOUND);
3340 return FALSE;
3343 SetLastError(NOERROR);
3344 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
3345 *(BYTE **)pvEncoded = NULL;
3346 if (!HIWORD(lpszStructType))
3348 switch (LOWORD(lpszStructType))
3350 case (WORD)X509_CERT:
3351 encodeFunc = CRYPT_AsnEncodeCert;
3352 break;
3353 case (WORD)X509_CERT_TO_BE_SIGNED:
3354 encodeFunc = CRYPT_AsnEncodeCertInfo;
3355 break;
3356 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
3357 encodeFunc = CRYPT_AsnEncodeCRLInfo;
3358 break;
3359 case (WORD)X509_EXTENSIONS:
3360 encodeFunc = CRYPT_AsnEncodeExtensions;
3361 break;
3362 case (WORD)X509_NAME_VALUE:
3363 encodeFunc = CRYPT_AsnEncodeNameValue;
3364 break;
3365 case (WORD)X509_NAME:
3366 encodeFunc = CRYPT_AsnEncodeName;
3367 break;
3368 case (WORD)X509_PUBLIC_KEY_INFO:
3369 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
3370 break;
3371 case (WORD)X509_AUTHORITY_KEY_ID:
3372 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3373 break;
3374 case (WORD)X509_ALTERNATE_NAME:
3375 encodeFunc = CRYPT_AsnEncodeAltName;
3376 break;
3377 case (WORD)X509_BASIC_CONSTRAINTS:
3378 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3379 break;
3380 case (WORD)X509_BASIC_CONSTRAINTS2:
3381 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3382 break;
3383 case (WORD)RSA_CSP_PUBLICKEYBLOB:
3384 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
3385 break;
3386 case (WORD)X509_UNICODE_NAME:
3387 encodeFunc = CRYPT_AsnEncodeUnicodeName;
3388 break;
3389 case (WORD)PKCS_CONTENT_INFO:
3390 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
3391 break;
3392 case (WORD)PKCS_ATTRIBUTE:
3393 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
3394 break;
3395 case (WORD)X509_UNICODE_NAME_VALUE:
3396 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
3397 break;
3398 case (WORD)X509_OCTET_STRING:
3399 encodeFunc = CRYPT_AsnEncodeOctets;
3400 break;
3401 case (WORD)X509_BITS:
3402 case (WORD)X509_KEY_USAGE:
3403 encodeFunc = CRYPT_AsnEncodeBits;
3404 break;
3405 case (WORD)X509_INTEGER:
3406 encodeFunc = CRYPT_AsnEncodeInt;
3407 break;
3408 case (WORD)X509_MULTI_BYTE_INTEGER:
3409 encodeFunc = CRYPT_AsnEncodeInteger;
3410 break;
3411 case (WORD)X509_MULTI_BYTE_UINT:
3412 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
3413 break;
3414 case (WORD)X509_ENUMERATED:
3415 encodeFunc = CRYPT_AsnEncodeEnumerated;
3416 break;
3417 case (WORD)X509_CHOICE_OF_TIME:
3418 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
3419 break;
3420 case (WORD)X509_AUTHORITY_KEY_ID2:
3421 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3422 break;
3423 case (WORD)X509_SEQUENCE_OF_ANY:
3424 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
3425 break;
3426 case (WORD)PKCS_UTC_TIME:
3427 encodeFunc = CRYPT_AsnEncodeUtcTime;
3428 break;
3429 case (WORD)X509_CRL_DIST_POINTS:
3430 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3431 break;
3432 case (WORD)X509_ENHANCED_KEY_USAGE:
3433 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3434 break;
3435 case (WORD)PKCS_ATTRIBUTES:
3436 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3437 break;
3438 case (WORD)X509_ISSUING_DIST_POINT:
3439 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3440 break;
3441 case (WORD)PKCS7_SIGNER_INFO:
3442 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
3443 break;
3444 default:
3445 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
3448 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3449 encodeFunc = CRYPT_AsnEncodeExtensions;
3450 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3451 encodeFunc = CRYPT_AsnEncodeUtcTime;
3452 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
3453 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3454 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
3455 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3456 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3457 encodeFunc = CRYPT_AsnEncodeEnumerated;
3458 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3459 encodeFunc = CRYPT_AsnEncodeBits;
3460 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3461 encodeFunc = CRYPT_AsnEncodeOctets;
3462 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3463 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3464 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3465 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3466 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3467 encodeFunc = CRYPT_AsnEncodeAltName;
3468 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3469 encodeFunc = CRYPT_AsnEncodeAltName;
3470 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3471 encodeFunc = CRYPT_AsnEncodeAltName;
3472 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3473 encodeFunc = CRYPT_AsnEncodeAltName;
3474 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3475 encodeFunc = CRYPT_AsnEncodeAltName;
3476 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3477 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3478 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3479 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3480 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3481 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3482 else
3483 TRACE("OID %s not found or unimplemented, looking for DLL\n",
3484 debugstr_a(lpszStructType));
3485 if (!encodeFunc)
3487 if (!set)
3488 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
3489 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3490 (void **)&encodeFunc, &hFunc);
3492 if (encodeFunc)
3493 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
3494 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
3495 else
3496 SetLastError(ERROR_FILE_NOT_FOUND);
3497 if (hFunc)
3498 CryptFreeOIDFunctionAddress(hFunc, 0);
3499 return ret;
3502 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV hCryptProv, DWORD dwKeySpec,
3503 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3505 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
3506 NULL, 0, NULL, pInfo, pcbInfo);
3509 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3510 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3511 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3513 BOOL ret;
3514 HCRYPTKEY key;
3515 static CHAR oid[] = szOID_RSA_RSA;
3517 TRACE("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv, dwKeySpec,
3518 dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo,
3519 pInfo, pcbInfo);
3521 if (!pszPublicKeyObjId)
3522 pszPublicKeyObjId = oid;
3523 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
3525 DWORD keySize = 0;
3527 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
3528 if (ret)
3530 LPBYTE pubKey = CryptMemAlloc(keySize);
3532 if (pubKey)
3534 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
3535 &keySize);
3536 if (ret)
3538 DWORD encodedLen = 0;
3540 ret = CryptEncodeObject(dwCertEncodingType,
3541 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
3542 if (ret)
3544 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
3545 strlen(pszPublicKeyObjId) + 1 + encodedLen;
3547 if (!pInfo)
3548 *pcbInfo = sizeNeeded;
3549 else if (*pcbInfo < sizeNeeded)
3551 SetLastError(ERROR_MORE_DATA);
3552 *pcbInfo = sizeNeeded;
3553 ret = FALSE;
3555 else
3557 pInfo->Algorithm.pszObjId = (char *)pInfo +
3558 sizeof(CERT_PUBLIC_KEY_INFO);
3559 lstrcpyA(pInfo->Algorithm.pszObjId,
3560 pszPublicKeyObjId);
3561 pInfo->Algorithm.Parameters.cbData = 0;
3562 pInfo->Algorithm.Parameters.pbData = NULL;
3563 pInfo->PublicKey.pbData =
3564 (BYTE *)pInfo->Algorithm.pszObjId
3565 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
3566 pInfo->PublicKey.cbData = encodedLen;
3567 pInfo->PublicKey.cUnusedBits = 0;
3568 ret = CryptEncodeObject(dwCertEncodingType,
3569 RSA_CSP_PUBLICKEYBLOB, pubKey,
3570 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
3574 CryptMemFree(pubKey);
3576 else
3577 ret = FALSE;
3579 CryptDestroyKey(key);
3581 return ret;
3584 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
3585 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3586 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
3588 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV hCryptProv, DWORD dwKeySpec,
3589 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
3590 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3592 static HCRYPTOIDFUNCSET set = NULL;
3593 BOOL ret;
3594 ExportPublicKeyInfoExFunc exportFunc = NULL;
3595 HCRYPTOIDFUNCADDR hFunc = NULL;
3597 TRACE("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv, dwKeySpec,
3598 dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo,
3599 pInfo, pcbInfo);
3601 if (!hCryptProv)
3603 SetLastError(ERROR_INVALID_PARAMETER);
3604 return FALSE;
3607 if (pszPublicKeyObjId)
3609 if (!set)
3610 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
3612 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
3613 0, (void **)&exportFunc, &hFunc);
3615 if (!exportFunc)
3616 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
3617 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
3618 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
3619 if (hFunc)
3620 CryptFreeOIDFunctionAddress(hFunc, 0);
3621 return ret;
3624 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
3625 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
3627 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
3628 0, 0, NULL, phKey);
3631 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3632 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3633 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3635 BOOL ret;
3636 DWORD pubKeySize = 0;
3638 TRACE("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv,
3639 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3641 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3642 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
3643 if (ret)
3645 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
3647 if (pubKey)
3649 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3650 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
3651 &pubKeySize);
3652 if (ret)
3653 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
3654 phKey);
3655 CryptMemFree(pubKey);
3657 else
3658 ret = FALSE;
3660 return ret;
3663 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
3664 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3665 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
3667 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3668 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3669 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3671 static HCRYPTOIDFUNCSET set = NULL;
3672 BOOL ret;
3673 ImportPublicKeyInfoExFunc importFunc = NULL;
3674 HCRYPTOIDFUNCADDR hFunc = NULL;
3676 TRACE("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv,
3677 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3679 if (!set)
3680 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
3681 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
3682 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
3683 if (!importFunc)
3684 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
3685 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
3686 pvAuxInfo, phKey);
3687 if (hFunc)
3688 CryptFreeOIDFunctionAddress(hFunc, 0);
3689 return ret;