source: trunk/src/crypt32/object.c@ 21354

Last change on this file since 21354 was 21354, checked in by rlwalsh, 16 years ago

eliminate VACPP warning & info msgs - see Ticket #1

File size: 83.1 KB
Line 
1/*
2 * crypt32 Crypt*Object functions
3 *
4 * Copyright 2007 Juan Lang
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20#include <stdarg.h>
21#include <string.h>
22#define NONAMELESSUNION
23#include "windef.h"
24#include "winbase.h"
25#include "wincrypt.h"
26#include "mssip.h"
27#include "winuser.h"
28#include "wintrust.h"
29#include "crypt32_private.h"
30#include "cryptres.h"
31#include "wine/unicode.h"
32#include "wine/debug.h"
33
34WINE_DEFAULT_DEBUG_CHANNEL(crypt);
35
36static BOOL CRYPT_ReadBlobFromFile(LPCWSTR fileName, PCERT_BLOB blob)
37{
38 BOOL ret = FALSE;
39 HANDLE file;
40
41 TRACE("%s\n", debugstr_w(fileName));
42
43 file = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL,
44 OPEN_EXISTING, 0, NULL);
45 if (file != INVALID_HANDLE_VALUE)
46 {
47 ret = TRUE;
48 blob->cbData = GetFileSize(file, NULL);
49 if (blob->cbData)
50 {
51 blob->pbData = CryptMemAlloc(blob->cbData);
52 if (blob->pbData)
53 {
54 DWORD read;
55
56 ret = ReadFile(file, blob->pbData, blob->cbData, &read, NULL);
57 }
58 }
59 CloseHandle(file);
60 }
61 TRACE("returning %d\n", ret);
62 return ret;
63}
64
65static BOOL CRYPT_QueryContextObject(DWORD dwObjectType, const void *pvObject,
66 DWORD dwExpectedContentTypeFlags, DWORD *pdwMsgAndCertEncodingType,
67 DWORD *pdwContentType, HCERTSTORE *phCertStore, const void **ppvContext)
68{
69 CERT_BLOB fileBlob;
70 const CERT_BLOB *blob;
71 HCERTSTORE store;
72 DWORD contentType;
73 BOOL ret;
74
75 switch (dwObjectType)
76 {
77 case CERT_QUERY_OBJECT_FILE:
78 /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so
79 * just read the file directly
80 */
81 ret = CRYPT_ReadBlobFromFile((LPCWSTR)pvObject, &fileBlob);
82 blob = &fileBlob;
83 break;
84 case CERT_QUERY_OBJECT_BLOB:
85 blob = (const CERT_BLOB *)pvObject;
86 ret = TRUE;
87 break;
88 default:
89 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
90 ret = FALSE;
91 }
92 if (!ret)
93 return FALSE;
94
95 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
96 CERT_STORE_CREATE_NEW_FLAG, NULL);
97 ret = FALSE;
98 if (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CERT)
99 {
100 ret = pCertInterface->addEncodedToStore(store, X509_ASN_ENCODING,
101 blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext);
102 if (ret)
103 contentType = CERT_QUERY_CONTENT_CERT;
104 }
105 if (!ret && (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CRL))
106 {
107 ret = pCRLInterface->addEncodedToStore(store, X509_ASN_ENCODING,
108 blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext);
109 if (ret)
110 contentType = CERT_QUERY_CONTENT_CRL;
111 }
112 if (!ret && (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CTL))
113 {
114 ret = pCTLInterface->addEncodedToStore(store, X509_ASN_ENCODING,
115 blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext);
116 if (ret)
117 contentType = CERT_QUERY_CONTENT_CTL;
118 }
119 if (ret)
120 {
121 if (pdwMsgAndCertEncodingType)
122 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING;
123 if (pdwContentType)
124 *pdwContentType = contentType;
125 if (phCertStore)
126 *phCertStore = CertDuplicateStore(store);
127 }
128 CertCloseStore(store, 0);
129 if (blob == &fileBlob)
130 CryptMemFree(blob->pbData);
131 TRACE("returning %d\n", ret);
132 return ret;
133}
134
135static BOOL CRYPT_QuerySerializedContextObject(DWORD dwObjectType,
136 const void *pvObject, DWORD dwExpectedContentTypeFlags,
137 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
138 HCERTSTORE *phCertStore, const void **ppvContext)
139{
140 CERT_BLOB fileBlob;
141 const CERT_BLOB *blob;
142 const WINE_CONTEXT_INTERFACE *contextInterface = NULL;
143 const void *context;
144 DWORD contextType;
145 BOOL ret;
146
147 switch (dwObjectType)
148 {
149 case CERT_QUERY_OBJECT_FILE:
150 /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so
151 * just read the file directly
152 */
153 ret = CRYPT_ReadBlobFromFile((LPCWSTR)pvObject, &fileBlob);
154 blob = &fileBlob;
155 break;
156 case CERT_QUERY_OBJECT_BLOB:
157 blob = (const CERT_BLOB *)pvObject;
158 ret = TRUE;
159 break;
160 default:
161 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
162 ret = FALSE;
163 }
164 if (!ret)
165 return FALSE;
166
167 context = CRYPT_ReadSerializedElement(blob->pbData, blob->cbData,
168 CERT_STORE_ALL_CONTEXT_FLAG, &contextType);
169 if (context)
170 {
171 DWORD contentType, certStoreOffset;
172
173 ret = TRUE;
174 switch (contextType)
175 {
176 case CERT_STORE_CERTIFICATE_CONTEXT:
177 contextInterface = pCertInterface;
178 contentType = CERT_QUERY_CONTENT_SERIALIZED_CERT;
179 certStoreOffset = offsetof(CERT_CONTEXT, hCertStore);
180 if (!(dwExpectedContentTypeFlags &
181 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT))
182 {
183 SetLastError(ERROR_INVALID_DATA);
184 ret = FALSE;
185 goto end;
186 }
187 break;
188 case CERT_STORE_CRL_CONTEXT:
189 contextInterface = pCRLInterface;
190 contentType = CERT_QUERY_CONTENT_SERIALIZED_CRL;
191 certStoreOffset = offsetof(CRL_CONTEXT, hCertStore);
192 if (!(dwExpectedContentTypeFlags &
193 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL))
194 {
195 SetLastError(ERROR_INVALID_DATA);
196 ret = FALSE;
197 goto end;
198 }
199 break;
200 case CERT_STORE_CTL_CONTEXT:
201 contextInterface = pCTLInterface;
202 contentType = CERT_QUERY_CONTENT_SERIALIZED_CTL;
203 certStoreOffset = offsetof(CTL_CONTEXT, hCertStore);
204 if (!(dwExpectedContentTypeFlags &
205 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL))
206 {
207 SetLastError(ERROR_INVALID_DATA);
208 ret = FALSE;
209 goto end;
210 }
211 break;
212 default:
213 SetLastError(ERROR_INVALID_DATA);
214 ret = FALSE;
215 goto end;
216 }
217 if (pdwMsgAndCertEncodingType)
218 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING;
219 if (pdwContentType)
220 *pdwContentType = contentType;
221 if (phCertStore)
222 *phCertStore = CertDuplicateStore(
223 *(HCERTSTORE *)((const BYTE *)context + certStoreOffset));
224 if (ppvContext)
225 *ppvContext = contextInterface->duplicate(context);
226 }
227
228end:
229 if (contextInterface && context)
230 contextInterface->confree(context);
231 if (blob == &fileBlob)
232 CryptMemFree(blob->pbData);
233 TRACE("returning %d\n", ret);
234 return ret;
235}
236
237static BOOL CRYPT_QuerySerializedStoreObject(DWORD dwObjectType,
238 const void *pvObject, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
239 HCERTSTORE *phCertStore, HCRYPTMSG *phMsg)
240{
241 LPCWSTR fileName = (LPCWSTR)pvObject;
242 HANDLE file;
243 BOOL ret = FALSE;
244
245 if (dwObjectType != CERT_QUERY_OBJECT_FILE)
246 {
247 FIXME("unimplemented for non-file type %d\n", dwObjectType);
248 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
249 return FALSE;
250 }
251 TRACE("%s\n", debugstr_w(fileName));
252 file = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL,
253 OPEN_EXISTING, 0, NULL);
254 if (file != INVALID_HANDLE_VALUE)
255 {
256 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
257 CERT_STORE_CREATE_NEW_FLAG, NULL);
258
259 ret = CRYPT_ReadSerializedStoreFromFile(file, store);
260 if (ret)
261 {
262 if (pdwMsgAndCertEncodingType)
263 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING;
264 if (pdwContentType)
265 *pdwContentType = CERT_QUERY_CONTENT_SERIALIZED_STORE;
266 if (phCertStore)
267 *phCertStore = CertDuplicateStore(store);
268 }
269 CertCloseStore(store, 0);
270 CloseHandle(file);
271 }
272 TRACE("returning %d\n", ret);
273 return ret;
274}
275
276/* Used to decode non-embedded messages */
277static BOOL CRYPT_QueryMessageObject(DWORD dwObjectType, const void *pvObject,
278 DWORD dwExpectedContentTypeFlags, DWORD *pdwMsgAndCertEncodingType,
279 DWORD *pdwContentType, HCERTSTORE *phCertStore, HCRYPTMSG *phMsg)
280{
281 CERT_BLOB fileBlob;
282 const CERT_BLOB *blob;
283 BOOL ret;
284 HCRYPTMSG msg = NULL;
285 DWORD encodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
286
287 switch (dwObjectType)
288 {
289 case CERT_QUERY_OBJECT_FILE:
290 /* This isn't an embedded PKCS7 message, so just read the file
291 * directly
292 */
293 ret = CRYPT_ReadBlobFromFile((LPCWSTR)pvObject, &fileBlob);
294 blob = &fileBlob;
295 break;
296 case CERT_QUERY_OBJECT_BLOB:
297 blob = (const CERT_BLOB *)pvObject;
298 ret = TRUE;
299 break;
300 default:
301 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
302 ret = FALSE;
303 }
304 if (!ret)
305 return FALSE;
306
307 ret = FALSE;
308 /* Try it first as a PKCS content info */
309 if ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED) ||
310 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED))
311 {
312 msg = CryptMsgOpenToDecode(encodingType, 0, 0, 0, NULL, NULL);
313 if (msg)
314 {
315 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE);
316 if (ret)
317 {
318 DWORD type, len = sizeof(type);
319
320 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &len);
321 if (ret)
322 {
323 if ((dwExpectedContentTypeFlags &
324 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED))
325 {
326 if (type != CMSG_SIGNED)
327 {
328 SetLastError(ERROR_INVALID_DATA);
329 ret = FALSE;
330 }
331 else if (pdwContentType)
332 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_SIGNED;
333 }
334 else if ((dwExpectedContentTypeFlags &
335 CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED))
336 {
337 if (type != CMSG_DATA)
338 {
339 SetLastError(ERROR_INVALID_DATA);
340 ret = FALSE;
341 }
342 else if (pdwContentType)
343 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_UNSIGNED;
344 }
345 }
346 }
347 if (!ret)
348 {
349 CryptMsgClose(msg);
350 msg = NULL;
351 }
352 }
353 }
354 /* Failing that, try explicitly typed messages */
355 if (!ret &&
356 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED))
357 {
358 msg = CryptMsgOpenToDecode(encodingType, 0, CMSG_SIGNED, 0, NULL, NULL);
359 if (msg)
360 {
361 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE);
362 if (!ret)
363 {
364 CryptMsgClose(msg);
365 msg = NULL;
366 }
367 }
368 if (msg && pdwContentType)
369 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_SIGNED;
370 }
371 if (!ret &&
372 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED))
373 {
374 msg = CryptMsgOpenToDecode(encodingType, 0, CMSG_DATA, 0, NULL, NULL);
375 if (msg)
376 {
377 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE);
378 if (!ret)
379 {
380 CryptMsgClose(msg);
381 msg = NULL;
382 }
383 }
384 if (msg && pdwContentType)
385 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_UNSIGNED;
386 }
387 if (pdwMsgAndCertEncodingType)
388 *pdwMsgAndCertEncodingType = encodingType;
389 if (msg)
390 {
391 if (phMsg)
392 *phMsg = msg;
393 if (phCertStore)
394 *phCertStore = CertOpenStore(CERT_STORE_PROV_MSG, encodingType, 0,
395 0, msg);
396 }
397 if (blob == &fileBlob)
398 CryptMemFree(blob->pbData);
399 TRACE("returning %d\n", ret);
400 return ret;
401}
402
403static BOOL CRYPT_QueryEmbeddedMessageObject(DWORD dwObjectType,
404 const void *pvObject, DWORD dwExpectedContentTypeFlags,
405 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
406 HCERTSTORE *phCertStore, HCRYPTMSG *phMsg)
407{
408 HANDLE file;
409 GUID subject;
410 BOOL ret = FALSE;
411
412 TRACE("%s\n", debugstr_w((LPCWSTR)pvObject));
413
414 if (dwObjectType != CERT_QUERY_OBJECT_FILE)
415 {
416 FIXME("don't know what to do for type %d embedded signed messages\n",
417 dwObjectType);
418 SetLastError(E_INVALIDARG);
419 return FALSE;
420 }
421 file = CreateFileW((LPCWSTR)pvObject, GENERIC_READ, FILE_SHARE_READ,
422 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
423 if (file != INVALID_HANDLE_VALUE)
424 {
425 ret = CryptSIPRetrieveSubjectGuid((LPCWSTR)pvObject, file, &subject);
426 if (ret)
427 {
428 SIP_DISPATCH_INFO sip;
429
430 memset(&sip, 0, sizeof(sip));
431 sip.cbSize = sizeof(sip);
432 ret = CryptSIPLoad(&subject, 0, &sip);
433 if (ret)
434 {
435 SIP_SUBJECTINFO subjectInfo;
436 CERT_BLOB blob;
437 DWORD encodingType;
438
439 memset(&subjectInfo, 0, sizeof(subjectInfo));
440 subjectInfo.cbSize = sizeof(subjectInfo);
441 subjectInfo.pgSubjectType = &subject;
442 subjectInfo.hFile = file;
443 subjectInfo.pwsFileName = (LPCWSTR)pvObject;
444 ret = sip.pfGet(&subjectInfo, &encodingType, 0, &blob.cbData,
445 NULL);
446 if (ret)
447 {
448 blob.pbData = CryptMemAlloc(blob.cbData);
449 if (blob.pbData)
450 {
451 ret = sip.pfGet(&subjectInfo, &encodingType, 0,
452 &blob.cbData, blob.pbData);
453 if (ret)
454 {
455 ret = CRYPT_QueryMessageObject(
456 CERT_QUERY_OBJECT_BLOB, &blob,
457 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED,
458 pdwMsgAndCertEncodingType, NULL, phCertStore,
459 phMsg);
460 if (ret && pdwContentType)
461 *pdwContentType =
462 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED;
463 }
464 CryptMemFree(blob.pbData);
465 }
466 else
467 {
468 SetLastError(ERROR_OUTOFMEMORY);
469 ret = FALSE;
470 }
471 }
472 }
473 }
474 CloseHandle(file);
475 }
476 TRACE("returning %d\n", ret);
477 return ret;
478}
479
480BOOL WINAPI CryptQueryObject(DWORD dwObjectType, const void *pvObject,
481 DWORD dwExpectedContentTypeFlags, DWORD dwExpectedFormatTypeFlags,
482 DWORD dwFlags, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
483 DWORD *pdwFormatType, HCERTSTORE *phCertStore, HCRYPTMSG *phMsg,
484 const void **ppvContext)
485{
486 static const DWORD unimplementedTypes =
487 CERT_QUERY_CONTENT_FLAG_PKCS10 | CERT_QUERY_CONTENT_FLAG_PFX |
488 CERT_QUERY_CONTENT_FLAG_CERT_PAIR;
489 BOOL ret = TRUE;
490
491 TRACE("(%08x, %p, %08x, %08x, %08x, %p, %p, %p, %p, %p, %p)\n",
492 dwObjectType, pvObject, dwExpectedContentTypeFlags,
493 dwExpectedFormatTypeFlags, dwFlags, pdwMsgAndCertEncodingType,
494 pdwContentType, pdwFormatType, phCertStore, phMsg, ppvContext);
495
496 if (dwExpectedContentTypeFlags & unimplementedTypes)
497 WARN("unimplemented for types %08x\n",
498 dwExpectedContentTypeFlags & unimplementedTypes);
499 if (!(dwExpectedFormatTypeFlags & CERT_QUERY_FORMAT_FLAG_BINARY))
500 {
501 FIXME("unimplemented for anything but binary\n");
502 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
503 return FALSE;
504 }
505 if (pdwFormatType)
506 *pdwFormatType = CERT_QUERY_FORMAT_BINARY;
507
508 if (phCertStore)
509 *phCertStore = NULL;
510 if (phMsg)
511 *phMsg = NULL;
512 if (ppvContext)
513 *ppvContext = NULL;
514
515 ret = FALSE;
516 if ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CERT) ||
517 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CRL) ||
518 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CTL))
519 {
520 ret = CRYPT_QueryContextObject(dwObjectType, pvObject,
521 dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType,
522 phCertStore, ppvContext);
523 }
524 if (!ret &&
525 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE))
526 {
527 ret = CRYPT_QuerySerializedStoreObject(dwObjectType, pvObject,
528 pdwMsgAndCertEncodingType, pdwContentType, phCertStore, phMsg);
529 }
530 if (!ret &&
531 ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT) ||
532 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL) ||
533 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL)))
534 {
535 ret = CRYPT_QuerySerializedContextObject(dwObjectType, pvObject,
536 dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType,
537 phCertStore, ppvContext);
538 }
539 if (!ret &&
540 ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED) ||
541 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED)))
542 {
543 ret = CRYPT_QueryMessageObject(dwObjectType, pvObject,
544 dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType,
545 phCertStore, phMsg);
546 }
547 if (!ret &&
548 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED))
549 {
550 ret = CRYPT_QueryEmbeddedMessageObject(dwObjectType, pvObject,
551 dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType,
552 phCertStore, phMsg);
553 }
554 TRACE("returning %d\n", ret);
555 return ret;
556}
557
558static BOOL WINAPI CRYPT_FormatHexString(DWORD dwCertEncodingType,
559 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
560 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
561 DWORD *pcbFormat)
562{
563 BOOL ret;
564 DWORD bytesNeeded;
565
566 if (cbEncoded)
567 bytesNeeded = (cbEncoded * 3) * sizeof(WCHAR);
568 else
569 bytesNeeded = sizeof(WCHAR);
570 if (!pbFormat)
571 {
572 *pcbFormat = bytesNeeded;
573 ret = TRUE;
574 }
575 else if (*pcbFormat < bytesNeeded)
576 {
577 *pcbFormat = bytesNeeded;
578 SetLastError(ERROR_MORE_DATA);
579 ret = FALSE;
580 }
581 else
582 {
583 static const WCHAR fmt[] = { '%','0','2','x',' ',0 };
584 static const WCHAR endFmt[] = { '%','0','2','x',0 };
585 DWORD i;
586 LPWSTR ptr = pbFormat;
587
588 *pcbFormat = bytesNeeded;
589 if (cbEncoded)
590 {
591 for (i = 0; i < cbEncoded; i++)
592 {
593 if (i < cbEncoded - 1)
594 ptr += sprintfW(ptr, fmt, pbEncoded[i]);
595 else
596 ptr += sprintfW(ptr, endFmt, pbEncoded[i]);
597 }
598 }
599 else
600 *ptr = 0;
601 ret = TRUE;
602 }
603 return ret;
604}
605
606#define MAX_STRING_RESOURCE_LEN 128
607
608static const WCHAR commaSpace[] = { ',',' ',0 };
609
610struct BitToString
611{
612 BYTE bit;
613 int id;
614 WCHAR str[MAX_STRING_RESOURCE_LEN];
615};
616
617static BOOL CRYPT_FormatBits(BYTE bits, const struct BitToString *map,
618 DWORD mapEntries, void *pbFormat, DWORD *pcbFormat, BOOL *first)
619{
620 DWORD bytesNeeded = sizeof(WCHAR);
621 int i;
622 BOOL ret = TRUE, localFirst = *first;
623
624 for (i = 0; i < mapEntries; i++)
625 if (bits & map[i].bit)
626 {
627 if (!localFirst)
628 bytesNeeded += strlenW(commaSpace) * sizeof(WCHAR);
629 localFirst = FALSE;
630 bytesNeeded += strlenW(map[i].str) * sizeof(WCHAR);
631 }
632 if (!pbFormat)
633 {
634 *first = localFirst;
635 *pcbFormat = bytesNeeded;
636 }
637 else if (*pcbFormat < bytesNeeded)
638 {
639 *first = localFirst;
640 *pcbFormat = bytesNeeded;
641 SetLastError(ERROR_MORE_DATA);
642 ret = FALSE;
643 }
644 else
645 {
646 LPWSTR str = pbFormat;
647
648 localFirst = *first;
649 *pcbFormat = bytesNeeded;
650 for (i = 0; i < mapEntries; i++)
651 if (bits & map[i].bit)
652 {
653 if (!localFirst)
654 {
655 strcpyW(str, commaSpace);
656 str += strlenW(commaSpace);
657 }
658 localFirst = FALSE;
659 strcpyW(str, map[i].str);
660 str += strlenW(map[i].str);
661 }
662 *first = localFirst;
663 }
664 return ret;
665}
666
667static struct BitToString keyUsageByte0Map[] = {
668 { CERT_DIGITAL_SIGNATURE_KEY_USAGE, IDS_DIGITAL_SIGNATURE, { 0 } },
669 { CERT_NON_REPUDIATION_KEY_USAGE, IDS_NON_REPUDIATION, { 0 } },
670 { CERT_KEY_ENCIPHERMENT_KEY_USAGE, IDS_KEY_ENCIPHERMENT, { 0 } },
671 { CERT_DATA_ENCIPHERMENT_KEY_USAGE, IDS_DATA_ENCIPHERMENT, { 0 } },
672 { CERT_KEY_AGREEMENT_KEY_USAGE, IDS_KEY_AGREEMENT, { 0 } },
673 { CERT_KEY_CERT_SIGN_KEY_USAGE, IDS_CERT_SIGN, { 0 } },
674 { CERT_OFFLINE_CRL_SIGN_KEY_USAGE, IDS_OFFLINE_CRL_SIGN, { 0 } },
675 { CERT_CRL_SIGN_KEY_USAGE, IDS_CRL_SIGN, { 0 } },
676 { CERT_ENCIPHER_ONLY_KEY_USAGE, IDS_ENCIPHER_ONLY, { 0 } },
677};
678static struct BitToString keyUsageByte1Map[] = {
679 { CERT_DECIPHER_ONLY_KEY_USAGE, IDS_DECIPHER_ONLY, { 0 } },
680};
681
682static BOOL WINAPI CRYPT_FormatKeyUsage(DWORD dwCertEncodingType,
683 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
684 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
685 DWORD *pcbFormat)
686{
687 DWORD size;
688 CRYPT_BIT_BLOB *bits;
689 BOOL ret;
690
691 if (!cbEncoded)
692 {
693 SetLastError(E_INVALIDARG);
694 return FALSE;
695 }
696 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_KEY_USAGE,
697 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &bits, &size)) != FALSE)
698 {
699 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
700 DWORD bytesNeeded = sizeof(WCHAR);
701
702 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable,
703 sizeof(infoNotAvailable) / sizeof(infoNotAvailable[0]));
704 if (!bits->cbData || bits->cbData > 2)
705 {
706 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR);
707 if (!pbFormat)
708 *pcbFormat = bytesNeeded;
709 else if (*pcbFormat < bytesNeeded)
710 {
711 *pcbFormat = bytesNeeded;
712 SetLastError(ERROR_MORE_DATA);
713 ret = FALSE;
714 }
715 else
716 {
717 LPWSTR str = pbFormat;
718
719 *pcbFormat = bytesNeeded;
720 strcpyW(str, infoNotAvailable);
721 }
722 }
723 else
724 {
725 static BOOL stringsLoaded = FALSE;
726 int i;
727 DWORD bitStringLen;
728 BOOL first = TRUE;
729
730 if (!stringsLoaded)
731 {
732 for (i = 0;
733 i < sizeof(keyUsageByte0Map) / sizeof(keyUsageByte0Map[0]);
734 i++)
735 LoadStringW(hInstance, keyUsageByte0Map[i].id,
736 keyUsageByte0Map[i].str, MAX_STRING_RESOURCE_LEN);
737 for (i = 0;
738 i < sizeof(keyUsageByte1Map) / sizeof(keyUsageByte1Map[0]);
739 i++)
740 LoadStringW(hInstance, keyUsageByte1Map[i].id,
741 keyUsageByte1Map[i].str, MAX_STRING_RESOURCE_LEN);
742 stringsLoaded = TRUE;
743 }
744 CRYPT_FormatBits(bits->pbData[0], keyUsageByte0Map,
745 sizeof(keyUsageByte0Map) / sizeof(keyUsageByte0Map[0]),
746 NULL, &bitStringLen, &first);
747 bytesNeeded += bitStringLen;
748 if (bits->cbData == 2)
749 {
750 CRYPT_FormatBits(bits->pbData[1], keyUsageByte1Map,
751 sizeof(keyUsageByte1Map) / sizeof(keyUsageByte1Map[0]),
752 NULL, &bitStringLen, &first);
753 bytesNeeded += bitStringLen;
754 }
755 bytesNeeded += 3 * sizeof(WCHAR); /* " (" + ")" */
756 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData,
757 bits->cbData, NULL, &size);
758 bytesNeeded += size;
759 if (!pbFormat)
760 *pcbFormat = bytesNeeded;
761 else if (*pcbFormat < bytesNeeded)
762 {
763 *pcbFormat = bytesNeeded;
764 SetLastError(ERROR_MORE_DATA);
765 ret = FALSE;
766 }
767 else
768 {
769 LPWSTR str = pbFormat;
770
771 bitStringLen = bytesNeeded;
772 first = TRUE;
773 CRYPT_FormatBits(bits->pbData[0], keyUsageByte0Map,
774 sizeof(keyUsageByte0Map) / sizeof(keyUsageByte0Map[0]),
775 str, &bitStringLen, &first);
776 str += bitStringLen / sizeof(WCHAR) - 1;
777 if (bits->cbData == 2)
778 {
779 bitStringLen = bytesNeeded;
780 CRYPT_FormatBits(bits->pbData[1], keyUsageByte1Map,
781 sizeof(keyUsageByte1Map) / sizeof(keyUsageByte1Map[0]),
782 str, &bitStringLen, &first);
783 str += bitStringLen / sizeof(WCHAR) - 1;
784 }
785 *str++ = ' ';
786 *str++ = '(';
787 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData,
788 bits->cbData, str, &size);
789 str += size / sizeof(WCHAR) - 1;
790 *str++ = ')';
791 *str = 0;
792 }
793 }
794 LocalFree((HANDLE)bits);
795 }
796 return ret;
797}
798
799static const WCHAR crlf[] = { '\r','\n',0 };
800
801static WCHAR subjectTypeHeader[MAX_STRING_RESOURCE_LEN];
802static WCHAR subjectTypeCA[MAX_STRING_RESOURCE_LEN];
803static WCHAR subjectTypeEndCert[MAX_STRING_RESOURCE_LEN];
804static WCHAR pathLengthHeader[MAX_STRING_RESOURCE_LEN];
805
806static BOOL WINAPI CRYPT_FormatBasicConstraints2(DWORD dwCertEncodingType,
807 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
808 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
809 DWORD *pcbFormat)
810{
811 DWORD size;
812 CERT_BASIC_CONSTRAINTS2_INFO *info;
813 BOOL ret;
814
815 if (!cbEncoded)
816 {
817 SetLastError(E_INVALIDARG);
818 return FALSE;
819 }
820 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_BASIC_CONSTRAINTS2,
821 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)) != FALSE)
822 {
823 static const WCHAR pathFmt[] = { '%','d',0 };
824 static BOOL stringsLoaded = FALSE;
825 DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */
826 WCHAR pathLength[MAX_STRING_RESOURCE_LEN];
827 LPCWSTR sep, subjectType;
828 DWORD sepLen;
829
830 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
831 {
832 sep = crlf;
833 sepLen = strlenW(crlf) * sizeof(WCHAR);
834 }
835 else
836 {
837 sep = commaSpace;
838 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
839 }
840
841 if (!stringsLoaded)
842 {
843 LoadStringW(hInstance, IDS_SUBJECT_TYPE, subjectTypeHeader,
844 sizeof(subjectTypeHeader) / sizeof(subjectTypeHeader[0]));
845 LoadStringW(hInstance, IDS_SUBJECT_TYPE_CA, subjectTypeCA,
846 sizeof(subjectTypeCA) / sizeof(subjectTypeCA[0]));
847 LoadStringW(hInstance, IDS_SUBJECT_TYPE_END_CERT,
848 subjectTypeEndCert,
849 sizeof(subjectTypeEndCert) / sizeof(subjectTypeEndCert[0]));
850 LoadStringW(hInstance, IDS_PATH_LENGTH, pathLengthHeader,
851 sizeof(pathLengthHeader) / sizeof(pathLengthHeader[0]));
852 stringsLoaded = TRUE;
853 }
854 bytesNeeded += strlenW(subjectTypeHeader) * sizeof(WCHAR);
855 if (info->fCA)
856 subjectType = subjectTypeCA;
857 else
858 subjectType = subjectTypeEndCert;
859 bytesNeeded += strlenW(subjectType) * sizeof(WCHAR);
860 bytesNeeded += sepLen;
861 bytesNeeded += strlenW(pathLengthHeader) * sizeof(WCHAR);
862 if (info->fPathLenConstraint)
863 sprintfW(pathLength, pathFmt, info->dwPathLenConstraint);
864 else
865 LoadStringW(hInstance, IDS_PATH_LENGTH_NONE, pathLength,
866 sizeof(pathLength) / sizeof(pathLength[0]));
867 bytesNeeded += strlenW(pathLength) * sizeof(WCHAR);
868 if (!pbFormat)
869 *pcbFormat = bytesNeeded;
870 else if (*pcbFormat < bytesNeeded)
871 {
872 *pcbFormat = bytesNeeded;
873 SetLastError(ERROR_MORE_DATA);
874 ret = FALSE;
875 }
876 else
877 {
878 LPWSTR str = pbFormat;
879
880 *pcbFormat = bytesNeeded;
881 strcpyW(str, subjectTypeHeader);
882 str += strlenW(subjectTypeHeader);
883 strcpyW(str, subjectType);
884 str += strlenW(subjectType);
885 strcpyW(str, sep);
886 str += sepLen / sizeof(WCHAR);
887 strcpyW(str, pathLengthHeader);
888 str += strlenW(pathLengthHeader);
889 strcpyW(str, pathLength);
890 str += strlenW(pathLength);
891 }
892 LocalFree((HANDLE)info);
893 }
894 return ret;
895}
896
897static BOOL CRYPT_FormatHexStringWithPrefix(CRYPT_DATA_BLOB *blob, int id,
898 LPWSTR str, DWORD *pcbStr)
899{
900 WCHAR buf[MAX_STRING_RESOURCE_LEN];
901 DWORD bytesNeeded;
902 BOOL ret;
903
904 LoadStringW(hInstance, id, buf, sizeof(buf) / sizeof(buf[0]));
905 CRYPT_FormatHexString(X509_ASN_ENCODING, 0, 0, NULL, NULL,
906 blob->pbData, blob->cbData, NULL, &bytesNeeded);
907 bytesNeeded += strlenW(buf) * sizeof(WCHAR);
908 if (!str)
909 {
910 *pcbStr = bytesNeeded;
911 ret = TRUE;
912 }
913 else if (*pcbStr < bytesNeeded)
914 {
915 *pcbStr = bytesNeeded;
916 SetLastError(ERROR_MORE_DATA);
917 ret = FALSE;
918 }
919 else
920 {
921 *pcbStr = bytesNeeded;
922 strcpyW(str, buf);
923 str += strlenW(str);
924 bytesNeeded -= strlenW(str) * sizeof(WCHAR);
925 ret = CRYPT_FormatHexString(X509_ASN_ENCODING, 0, 0, NULL, NULL,
926 blob->pbData, blob->cbData, str, &bytesNeeded);
927 }
928 return ret;
929}
930
931static BOOL CRYPT_FormatKeyId(CRYPT_DATA_BLOB *keyId, LPWSTR str,
932 DWORD *pcbStr)
933{
934 return CRYPT_FormatHexStringWithPrefix(keyId, IDS_KEY_ID, str, pcbStr);
935}
936
937static BOOL CRYPT_FormatCertSerialNumber(CRYPT_DATA_BLOB *serialNum, LPWSTR str,
938 DWORD *pcbStr)
939{
940 return CRYPT_FormatHexStringWithPrefix(serialNum, IDS_CERT_SERIAL_NUMBER,
941 str, pcbStr);
942}
943
944static const WCHAR indent[] = { ' ',' ',' ',' ',' ',0 };
945static const WCHAR colonCrlf[] = { ':','\r','\n',0 };
946
947static BOOL CRYPT_FormatAltNameEntry(DWORD dwFormatStrType, DWORD indentLevel,
948 CERT_ALT_NAME_ENTRY *entry, LPWSTR str, DWORD *pcbStr)
949{
950 BOOL ret;
951 WCHAR buf[MAX_STRING_RESOURCE_LEN];
952 WCHAR mask[MAX_STRING_RESOURCE_LEN];
953 WCHAR ipAddrBuf[32];
954 WCHAR maskBuf[16];
955 DWORD bytesNeeded = sizeof(WCHAR);
956 DWORD strType = CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG;
957
958 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
959 bytesNeeded += indentLevel * strlenW(indent) * sizeof(WCHAR);
960 switch (entry->dwAltNameChoice)
961 {
962 case CERT_ALT_NAME_RFC822_NAME:
963 LoadStringW(hInstance, IDS_ALT_NAME_RFC822_NAME, buf,
964 sizeof(buf) / sizeof(buf[0]));
965 bytesNeeded += strlenW(entry->u.pwszRfc822Name) * sizeof(WCHAR);
966 ret = TRUE;
967 break;
968 case CERT_ALT_NAME_DNS_NAME:
969 LoadStringW(hInstance, IDS_ALT_NAME_DNS_NAME, buf,
970 sizeof(buf) / sizeof(buf[0]));
971 bytesNeeded += strlenW(entry->u.pwszDNSName) * sizeof(WCHAR);
972 ret = TRUE;
973 break;
974 case CERT_ALT_NAME_DIRECTORY_NAME:
975 {
976 DWORD directoryNameLen;
977
978 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
979 strType |= CERT_NAME_STR_CRLF_FLAG;
980 directoryNameLen = cert_name_to_str_with_indent(X509_ASN_ENCODING,
981 indentLevel + 1, &entry->u.DirectoryName, strType, NULL, 0);
982 LoadStringW(hInstance, IDS_ALT_NAME_DIRECTORY_NAME, buf,
983 sizeof(buf) / sizeof(buf[0]));
984 bytesNeeded += (directoryNameLen - 1) * sizeof(WCHAR);
985 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
986 bytesNeeded += strlenW(colonCrlf) * sizeof(WCHAR);
987 else
988 bytesNeeded += sizeof(WCHAR); /* '=' */
989 ret = TRUE;
990 break;
991 }
992 case CERT_ALT_NAME_URL:
993 LoadStringW(hInstance, IDS_ALT_NAME_URL, buf,
994 sizeof(buf) / sizeof(buf[0]));
995 bytesNeeded += strlenW(entry->u.pwszURL) * sizeof(WCHAR);
996 ret = TRUE;
997 break;
998 case CERT_ALT_NAME_IP_ADDRESS:
999 {
1000 static const WCHAR ipAddrWithMaskFmt[] = { '%','d','.','%','d','.',
1001 '%','d','.','%','d','/','%','d','.','%','d','.','%','d','.','%','d',0
1002 };
1003 static const WCHAR ipAddrFmt[] = { '%','d','.','%','d','.','%','d',
1004 '.','%','d',0 };
1005
1006 LoadStringW(hInstance, IDS_ALT_NAME_IP_ADDRESS, buf,
1007 sizeof(buf) / sizeof(buf[0]));
1008 if (entry->u.IPAddress.cbData == 8)
1009 {
1010 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1011 {
1012 LoadStringW(hInstance, IDS_ALT_NAME_MASK, mask,
1013 sizeof(mask) / sizeof(mask[0]));
1014 bytesNeeded += strlenW(mask) * sizeof(WCHAR);
1015 sprintfW(ipAddrBuf, ipAddrFmt,
1016 entry->u.IPAddress.pbData[0],
1017 entry->u.IPAddress.pbData[1],
1018 entry->u.IPAddress.pbData[2],
1019 entry->u.IPAddress.pbData[3]);
1020 bytesNeeded += strlenW(ipAddrBuf) * sizeof(WCHAR);
1021 /* indent again, for the mask line */
1022 bytesNeeded += indentLevel * strlenW(indent) * sizeof(WCHAR);
1023 sprintfW(maskBuf, ipAddrFmt,
1024 entry->u.IPAddress.pbData[4],
1025 entry->u.IPAddress.pbData[5],
1026 entry->u.IPAddress.pbData[6],
1027 entry->u.IPAddress.pbData[7]);
1028 bytesNeeded += strlenW(maskBuf) * sizeof(WCHAR);
1029 bytesNeeded += strlenW(crlf) * sizeof(WCHAR);
1030 }
1031 else
1032 {
1033 sprintfW(ipAddrBuf, ipAddrWithMaskFmt,
1034 entry->u.IPAddress.pbData[0],
1035 entry->u.IPAddress.pbData[1],
1036 entry->u.IPAddress.pbData[2],
1037 entry->u.IPAddress.pbData[3],
1038 entry->u.IPAddress.pbData[4],
1039 entry->u.IPAddress.pbData[5],
1040 entry->u.IPAddress.pbData[6],
1041 entry->u.IPAddress.pbData[7]);
1042 bytesNeeded += (strlenW(ipAddrBuf) + 1) * sizeof(WCHAR);
1043 }
1044 ret = TRUE;
1045 }
1046 else
1047 {
1048 FIXME("unknown IP address format (%d bytes)\n",
1049 entry->u.IPAddress.cbData);
1050 ret = FALSE;
1051 }
1052 break;
1053 }
1054 default:
1055 FIXME("unimplemented for %d\n", entry->dwAltNameChoice);
1056 ret = FALSE;
1057 }
1058 if (ret)
1059 {
1060 bytesNeeded += strlenW(buf) * sizeof(WCHAR);
1061 if (!str)
1062 *pcbStr = bytesNeeded;
1063 else if (*pcbStr < bytesNeeded)
1064 {
1065 *pcbStr = bytesNeeded;
1066 SetLastError(ERROR_MORE_DATA);
1067 ret = FALSE;
1068 }
1069 else
1070 {
1071 DWORD i;
1072
1073 *pcbStr = bytesNeeded;
1074 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1075 {
1076 for (i = 0; i < indentLevel; i++)
1077 {
1078 strcpyW(str, indent);
1079 str += strlenW(indent);
1080 }
1081 }
1082 strcpyW(str, buf);
1083 str += strlenW(str);
1084 switch (entry->dwAltNameChoice)
1085 {
1086 case CERT_ALT_NAME_RFC822_NAME:
1087 case CERT_ALT_NAME_DNS_NAME:
1088 case CERT_ALT_NAME_URL:
1089 strcpyW(str, entry->u.pwszURL);
1090 break;
1091 case CERT_ALT_NAME_DIRECTORY_NAME:
1092 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1093 {
1094 strcpyW(str, colonCrlf);
1095 str += strlenW(colonCrlf);
1096 }
1097 else
1098 *str++ = '=';
1099 cert_name_to_str_with_indent(X509_ASN_ENCODING,
1100 indentLevel + 1, &entry->u.DirectoryName, strType, str,
1101 bytesNeeded / sizeof(WCHAR));
1102 break;
1103 case CERT_ALT_NAME_IP_ADDRESS:
1104 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1105 {
1106 strcpyW(str, ipAddrBuf);
1107 str += strlenW(ipAddrBuf);
1108 strcpyW(str, crlf);
1109 str += strlenW(crlf);
1110 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1111 {
1112 for (i = 0; i < indentLevel; i++)
1113 {
1114 strcpyW(str, indent);
1115 str += strlenW(indent);
1116 }
1117 }
1118 strcpyW(str, mask);
1119 str += strlenW(mask);
1120 strcpyW(str, maskBuf);
1121 }
1122 else
1123 strcpyW(str, ipAddrBuf);
1124 break;
1125 }
1126 }
1127 }
1128 return ret;
1129}
1130
1131static BOOL CRYPT_FormatAltNameInfo(DWORD dwFormatStrType, DWORD indentLevel,
1132 CERT_ALT_NAME_INFO *name, LPWSTR str, DWORD *pcbStr)
1133{
1134 DWORD i, size, bytesNeeded = 0;
1135 BOOL ret = TRUE;
1136 LPCWSTR sep;
1137 DWORD sepLen;
1138
1139 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1140 {
1141 sep = crlf;
1142 sepLen = strlenW(crlf) * sizeof(WCHAR);
1143 }
1144 else
1145 {
1146 sep = commaSpace;
1147 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
1148 }
1149
1150 for (i = 0; ret && i < name->cAltEntry; i++)
1151 {
1152 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, indentLevel,
1153 &name->rgAltEntry[i], NULL, &size);
1154 if (ret)
1155 {
1156 bytesNeeded += size - sizeof(WCHAR);
1157 if (i < name->cAltEntry - 1)
1158 bytesNeeded += sepLen;
1159 }
1160 }
1161 if (ret)
1162 {
1163 bytesNeeded += sizeof(WCHAR);
1164 if (!str)
1165 *pcbStr = bytesNeeded;
1166 else if (*pcbStr < bytesNeeded)
1167 {
1168 *pcbStr = bytesNeeded;
1169 SetLastError(ERROR_MORE_DATA);
1170 ret = FALSE;
1171 }
1172 else
1173 {
1174 *pcbStr = bytesNeeded;
1175 for (i = 0; ret && i < name->cAltEntry; i++)
1176 {
1177 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, indentLevel,
1178 &name->rgAltEntry[i], str, &size);
1179 if (ret)
1180 {
1181 str += size / sizeof(WCHAR) - 1;
1182 if (i < name->cAltEntry - 1)
1183 {
1184 strcpyW(str, sep);
1185 str += sepLen / sizeof(WCHAR);
1186 }
1187 }
1188 }
1189 }
1190 }
1191 return ret;
1192}
1193
1194static const WCHAR colonSep[] = { ':',' ',0 };
1195
1196static BOOL WINAPI CRYPT_FormatAltName(DWORD dwCertEncodingType,
1197 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1198 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1199 DWORD *pcbFormat)
1200{
1201 BOOL ret;
1202 CERT_ALT_NAME_INFO *info;
1203 DWORD size;
1204
1205 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_ALTERNATE_NAME,
1206 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)) != FALSE)
1207 {
1208 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 0, info, pbFormat, pcbFormat);
1209 LocalFree((HANDLE)info);
1210 }
1211 return ret;
1212}
1213
1214static BOOL CRYPT_FormatCertIssuer(DWORD dwFormatStrType,
1215 CERT_ALT_NAME_INFO *issuer, LPWSTR str, DWORD *pcbStr)
1216{
1217 WCHAR buf[MAX_STRING_RESOURCE_LEN];
1218 DWORD bytesNeeded, sepLen;
1219 LPCWSTR sep;
1220 BOOL ret;
1221
1222 LoadStringW(hInstance, IDS_CERT_ISSUER, buf, sizeof(buf) / sizeof(buf[0]));
1223 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 1, issuer, NULL,
1224 &bytesNeeded);
1225 bytesNeeded += strlenW(buf) * sizeof(WCHAR);
1226 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1227 {
1228 sep = colonCrlf;
1229 sepLen = strlenW(colonCrlf) * sizeof(WCHAR);
1230 }
1231 else
1232 {
1233 sep = colonSep;
1234 sepLen = strlenW(colonSep) * sizeof(WCHAR);
1235 }
1236 bytesNeeded += sepLen;
1237 if (ret)
1238 {
1239 if (!str)
1240 *pcbStr = bytesNeeded;
1241 else if (*pcbStr < bytesNeeded)
1242 {
1243 *pcbStr = bytesNeeded;
1244 SetLastError(ERROR_MORE_DATA);
1245 ret = FALSE;
1246 }
1247 else
1248 {
1249 *pcbStr = bytesNeeded;
1250 strcpyW(str, buf);
1251 bytesNeeded -= strlenW(str) * sizeof(WCHAR);
1252 str += strlenW(str);
1253 strcpyW(str, sep);
1254 str += sepLen / sizeof(WCHAR);
1255 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 1, issuer, str,
1256 &bytesNeeded);
1257 }
1258 }
1259 return ret;
1260}
1261
1262static BOOL WINAPI CRYPT_FormatAuthorityKeyId2(DWORD dwCertEncodingType,
1263 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1264 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1265 DWORD *pcbFormat)
1266{
1267 CERT_AUTHORITY_KEY_ID2_INFO *info;
1268 DWORD size;
1269 BOOL ret = FALSE;
1270
1271 if (!cbEncoded)
1272 {
1273 SetLastError(E_INVALIDARG);
1274 return FALSE;
1275 }
1276 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_AUTHORITY_KEY_ID2,
1277 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)) != FALSE)
1278 {
1279 DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */
1280 LPCWSTR sep;
1281 DWORD sepLen;
1282 BOOL needSeparator = FALSE;
1283
1284 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1285 {
1286 sep = crlf;
1287 sepLen = strlenW(crlf) * sizeof(WCHAR);
1288 }
1289 else
1290 {
1291 sep = commaSpace;
1292 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
1293 }
1294
1295 if (info->KeyId.cbData)
1296 {
1297 needSeparator = TRUE;
1298 ret = CRYPT_FormatKeyId(&info->KeyId, NULL, &size);
1299 if (ret)
1300 {
1301 /* don't include NULL-terminator more than once */
1302 bytesNeeded += size - sizeof(WCHAR);
1303 }
1304 }
1305 if (info->AuthorityCertIssuer.cAltEntry)
1306 {
1307 if (needSeparator)
1308 bytesNeeded += sepLen;
1309 needSeparator = TRUE;
1310 ret = CRYPT_FormatCertIssuer(dwFormatStrType,
1311 &info->AuthorityCertIssuer, NULL, &size);
1312 if (ret)
1313 {
1314 /* don't include NULL-terminator more than once */
1315 bytesNeeded += size - sizeof(WCHAR);
1316 }
1317 }
1318 if (info->AuthorityCertSerialNumber.cbData)
1319 {
1320 if (needSeparator)
1321 bytesNeeded += sepLen;
1322 ret = CRYPT_FormatCertSerialNumber(
1323 &info->AuthorityCertSerialNumber, NULL, &size);
1324 if (ret)
1325 {
1326 /* don't include NULL-terminator more than once */
1327 bytesNeeded += size - sizeof(WCHAR);
1328 }
1329 }
1330 if (ret)
1331 {
1332 if (!pbFormat)
1333 *pcbFormat = bytesNeeded;
1334 else if (*pcbFormat < bytesNeeded)
1335 {
1336 *pcbFormat = bytesNeeded;
1337 SetLastError(ERROR_MORE_DATA);
1338 ret = FALSE;
1339 }
1340 else
1341 {
1342 LPWSTR str = pbFormat;
1343
1344 *pcbFormat = bytesNeeded;
1345 needSeparator = FALSE;
1346 if (info->KeyId.cbData)
1347 {
1348 needSeparator = TRUE;
1349 /* Overestimate size available, it's already been checked
1350 * above.
1351 */
1352 size = bytesNeeded;
1353 ret = CRYPT_FormatKeyId(&info->KeyId, str, &size);
1354 if (ret)
1355 str += size / sizeof(WCHAR) - 1;
1356 }
1357 if (info->AuthorityCertIssuer.cAltEntry)
1358 {
1359 if (needSeparator)
1360 {
1361 strcpyW(str, sep);
1362 str += sepLen / sizeof(WCHAR);
1363 }
1364 needSeparator = TRUE;
1365 /* Overestimate size available, it's already been checked
1366 * above.
1367 */
1368 size = bytesNeeded;
1369 ret = CRYPT_FormatCertIssuer(dwFormatStrType,
1370 &info->AuthorityCertIssuer, str, &size);
1371 if (ret)
1372 str += size / sizeof(WCHAR) - 1;
1373 }
1374 if (info->AuthorityCertSerialNumber.cbData)
1375 {
1376 if (needSeparator)
1377 {
1378 strcpyW(str, sep);
1379 str += sepLen / sizeof(WCHAR);
1380 }
1381 /* Overestimate size available, it's already been checked
1382 * above.
1383 */
1384 size = bytesNeeded;
1385 ret = CRYPT_FormatCertSerialNumber(
1386 &info->AuthorityCertSerialNumber, str, &size);
1387 }
1388 }
1389 }
1390 LocalFree((HANDLE)info);
1391 }
1392 return ret;
1393}
1394
1395static WCHAR aia[MAX_STRING_RESOURCE_LEN];
1396static WCHAR accessMethod[MAX_STRING_RESOURCE_LEN];
1397static WCHAR ocsp[MAX_STRING_RESOURCE_LEN];
1398static WCHAR caIssuers[MAX_STRING_RESOURCE_LEN];
1399static WCHAR unknown[MAX_STRING_RESOURCE_LEN];
1400static WCHAR accessLocation[MAX_STRING_RESOURCE_LEN];
1401
1402static BOOL WINAPI CRYPT_FormatAuthorityInfoAccess(DWORD dwCertEncodingType,
1403 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1404 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1405 DWORD *pcbFormat)
1406{
1407 CERT_AUTHORITY_INFO_ACCESS *info;
1408 DWORD size;
1409 BOOL ret = FALSE;
1410
1411 if (!cbEncoded)
1412 {
1413 SetLastError(E_INVALIDARG);
1414 return FALSE;
1415 }
1416 if ((ret = CryptDecodeObjectEx(dwCertEncodingType,
1417 X509_AUTHORITY_INFO_ACCESS, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG,
1418 NULL, &info, &size)) != FALSE)
1419 {
1420 DWORD bytesNeeded = sizeof(WCHAR);
1421
1422 if (!info->cAccDescr)
1423 {
1424 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
1425
1426 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable,
1427 sizeof(infoNotAvailable) / sizeof(infoNotAvailable[0]));
1428 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR);
1429 if (!pbFormat)
1430 *pcbFormat = bytesNeeded;
1431 else if (*pcbFormat < bytesNeeded)
1432 {
1433 *pcbFormat = bytesNeeded;
1434 SetLastError(ERROR_MORE_DATA);
1435 ret = FALSE;
1436 }
1437 else
1438 {
1439 *pcbFormat = bytesNeeded;
1440 strcpyW((LPWSTR)pbFormat, infoNotAvailable);
1441 }
1442 }
1443 else
1444 {
1445 static const WCHAR numFmt[] = { '%','d',0 };
1446 static const WCHAR equal[] = { '=',0 };
1447 static BOOL stringsLoaded = FALSE;
1448 DWORD i;
1449 LPCWSTR headingSep, accessMethodSep, locationSep;
1450 WCHAR accessDescrNum[11];
1451
1452 if (!stringsLoaded)
1453 {
1454 LoadStringW(hInstance, IDS_AIA, aia,
1455 sizeof(aia) / sizeof(aia[0]));
1456 LoadStringW(hInstance, IDS_ACCESS_METHOD, accessMethod,
1457 sizeof(accessMethod) / sizeof(accessMethod[0]));
1458 LoadStringW(hInstance, IDS_ACCESS_METHOD_OCSP, ocsp,
1459 sizeof(ocsp) / sizeof(ocsp[0]));
1460 LoadStringW(hInstance, IDS_ACCESS_METHOD_CA_ISSUERS, caIssuers,
1461 sizeof(caIssuers) / sizeof(caIssuers[0]));
1462 LoadStringW(hInstance, IDS_ACCESS_METHOD_UNKNOWN, unknown,
1463 sizeof(unknown) / sizeof(unknown[0]));
1464 LoadStringW(hInstance, IDS_ACCESS_LOCATION, accessLocation,
1465 sizeof(accessLocation) / sizeof(accessLocation[0]));
1466 stringsLoaded = TRUE;
1467 }
1468 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1469 {
1470 headingSep = crlf;
1471 accessMethodSep = crlf;
1472 locationSep = colonCrlf;
1473 }
1474 else
1475 {
1476 headingSep = colonSep;
1477 accessMethodSep = commaSpace;
1478 locationSep = equal;
1479 }
1480
1481 for (i = 0; ret && i < info->cAccDescr; i++)
1482 {
1483 /* Heading */
1484 bytesNeeded += sizeof(WCHAR); /* left bracket */
1485 sprintfW(accessDescrNum, numFmt, i + 1);
1486 bytesNeeded += strlenW(accessDescrNum) * sizeof(WCHAR);
1487 bytesNeeded += sizeof(WCHAR); /* right bracket */
1488 bytesNeeded += strlenW(aia) * sizeof(WCHAR);
1489 bytesNeeded += strlenW(headingSep) * sizeof(WCHAR);
1490 /* Access method */
1491 bytesNeeded += strlenW(accessMethod) * sizeof(WCHAR);
1492 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1493 bytesNeeded += strlenW(indent) * sizeof(WCHAR);
1494 if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1495 szOID_PKIX_OCSP))
1496 bytesNeeded += strlenW(ocsp) * sizeof(WCHAR);
1497 else if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1498 szOID_PKIX_CA_ISSUERS))
1499 bytesNeeded += strlenW(caIssuers) * sizeof(caIssuers);
1500 else
1501 bytesNeeded += strlenW(unknown) * sizeof(WCHAR);
1502 bytesNeeded += sizeof(WCHAR); /* space */
1503 bytesNeeded += sizeof(WCHAR); /* left paren */
1504 bytesNeeded += strlen(info->rgAccDescr[i].pszAccessMethod)
1505 * sizeof(WCHAR);
1506 bytesNeeded += sizeof(WCHAR); /* right paren */
1507 /* Delimiter between access method and location */
1508 bytesNeeded += strlenW(accessMethodSep) * sizeof(WCHAR);
1509 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1510 bytesNeeded += strlenW(indent) * sizeof(WCHAR);
1511 bytesNeeded += strlenW(accessLocation) * sizeof(WCHAR);
1512 bytesNeeded += strlenW(locationSep) * sizeof(WCHAR);
1513 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, 2,
1514 &info->rgAccDescr[i].AccessLocation, NULL, &size);
1515 if (ret)
1516 bytesNeeded += size - sizeof(WCHAR);
1517 /* Need extra delimiter between access method entries */
1518 if (i < info->cAccDescr - 1)
1519 bytesNeeded += strlenW(accessMethodSep) * sizeof(WCHAR);
1520 }
1521 if (ret)
1522 {
1523 if (!pbFormat)
1524 *pcbFormat = bytesNeeded;
1525 else if (*pcbFormat < bytesNeeded)
1526 {
1527 *pcbFormat = bytesNeeded;
1528 SetLastError(ERROR_MORE_DATA);
1529 ret = FALSE;
1530 }
1531 else
1532 {
1533 LPWSTR str = pbFormat;
1534 DWORD altNameEntrySize;
1535
1536 *pcbFormat = bytesNeeded;
1537 for (i = 0; ret && i < info->cAccDescr; i++)
1538 {
1539 LPCSTR oidPtr;
1540
1541 *str++ = '[';
1542 sprintfW(accessDescrNum, numFmt, i + 1);
1543 strcpyW(str, accessDescrNum);
1544 str += strlenW(accessDescrNum);
1545 *str++ = ']';
1546 strcpyW(str, aia);
1547 str += strlenW(aia);
1548 strcpyW(str, headingSep);
1549 str += strlenW(headingSep);
1550 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1551 {
1552 strcpyW(str, indent);
1553 str += strlenW(indent);
1554 }
1555 strcpyW(str, accessMethod);
1556 str += strlenW(accessMethod);
1557 if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1558 szOID_PKIX_OCSP))
1559 {
1560 strcpyW(str, ocsp);
1561 str += strlenW(ocsp);
1562 }
1563 else if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1564 szOID_PKIX_CA_ISSUERS))
1565 {
1566 strcpyW(str, caIssuers);
1567 str += strlenW(caIssuers);
1568 }
1569 else
1570 {
1571 strcpyW(str, unknown);
1572 str += strlenW(unknown);
1573 }
1574 *str++ = ' ';
1575 *str++ = '(';
1576 for (oidPtr = info->rgAccDescr[i].pszAccessMethod;
1577 *oidPtr; oidPtr++, str++)
1578 *str = *oidPtr;
1579 *str++ = ')';
1580 strcpyW(str, accessMethodSep);
1581 str += strlenW(accessMethodSep);
1582 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1583 {
1584 strcpyW(str, indent);
1585 str += strlenW(indent);
1586 }
1587 strcpyW(str, accessLocation);
1588 str += strlenW(accessLocation);
1589 strcpyW(str, locationSep);
1590 str += strlenW(locationSep);
1591 /* This overestimates the size available, but that
1592 * won't matter since we checked earlier whether enough
1593 * space for the entire string was available.
1594 */
1595 altNameEntrySize = bytesNeeded;
1596 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, 2,
1597 &info->rgAccDescr[i].AccessLocation, str,
1598 &altNameEntrySize);
1599 if (ret)
1600 str += altNameEntrySize / sizeof(WCHAR) - 1;
1601 if (i < info->cAccDescr - 1)
1602 {
1603 strcpyW(str, accessMethodSep);
1604 str += strlenW(accessMethodSep);
1605 }
1606 }
1607 }
1608 }
1609 }
1610 LocalFree((HANDLE)info);
1611 }
1612 return ret;
1613}
1614
1615static WCHAR keyCompromise[MAX_STRING_RESOURCE_LEN];
1616static WCHAR caCompromise[MAX_STRING_RESOURCE_LEN];
1617static WCHAR affiliationChanged[MAX_STRING_RESOURCE_LEN];
1618static WCHAR superseded[MAX_STRING_RESOURCE_LEN];
1619static WCHAR operationCeased[MAX_STRING_RESOURCE_LEN];
1620static WCHAR certificateHold[MAX_STRING_RESOURCE_LEN];
1621
1622struct reason_map_entry
1623{
1624 BYTE reasonBit;
1625 LPWSTR reason;
1626 int id;
1627};
1628static struct reason_map_entry reason_map[] = {
1629 { CRL_REASON_KEY_COMPROMISE_FLAG, keyCompromise, IDS_REASON_KEY_COMPROMISE },
1630 { CRL_REASON_CA_COMPROMISE_FLAG, caCompromise, IDS_REASON_CA_COMPROMISE },
1631 { CRL_REASON_AFFILIATION_CHANGED_FLAG, affiliationChanged,
1632 IDS_REASON_AFFILIATION_CHANGED },
1633 { CRL_REASON_SUPERSEDED_FLAG, superseded, IDS_REASON_SUPERSEDED },
1634 { CRL_REASON_CESSATION_OF_OPERATION_FLAG, operationCeased,
1635 IDS_REASON_CESSATION_OF_OPERATION },
1636 { CRL_REASON_CERTIFICATE_HOLD_FLAG, certificateHold,
1637 IDS_REASON_CERTIFICATE_HOLD },
1638};
1639
1640static BOOL CRYPT_FormatReason(DWORD dwFormatStrType,
1641 const CRYPT_BIT_BLOB *reasonFlags, LPWSTR str, DWORD *pcbStr)
1642{
1643 static const WCHAR sep[] = { ',',' ',0 };
1644 static const WCHAR bitsFmt[] = { ' ','(','%','0','2','x',')',0 };
1645 static BOOL stringsLoaded = FALSE;
1646 int i, numReasons = 0;
1647 BOOL ret = TRUE;
1648 DWORD bytesNeeded = sizeof(WCHAR);
1649 WCHAR bits[6];
1650
1651 if (!stringsLoaded)
1652 {
1653 for (i = 0; i < sizeof(reason_map) / sizeof(reason_map[0]); i++)
1654 LoadStringW(hInstance, reason_map[i].id, reason_map[i].reason,
1655 MAX_STRING_RESOURCE_LEN);
1656 stringsLoaded = TRUE;
1657 }
1658 /* No need to check reasonFlags->cbData, we already know it's positive.
1659 * Ignore any other bytes, as they're for undefined bits.
1660 */
1661 for (i = 0; i < sizeof(reason_map) / sizeof(reason_map[0]); i++)
1662 {
1663 if (reasonFlags->pbData[0] & reason_map[i].reasonBit)
1664 {
1665 bytesNeeded += strlenW(reason_map[i].reason) * sizeof(WCHAR);
1666 if (numReasons++)
1667 bytesNeeded += strlenW(sep) * sizeof(WCHAR);
1668 }
1669 }
1670 sprintfW(bits, bitsFmt, reasonFlags->pbData[0]);
1671 bytesNeeded += strlenW(bits);
1672 if (!str)
1673 *pcbStr = bytesNeeded;
1674 else if (*pcbStr < bytesNeeded)
1675 {
1676 *pcbStr = bytesNeeded;
1677 SetLastError(ERROR_MORE_DATA);
1678 ret = FALSE;
1679 }
1680 else
1681 {
1682 *pcbStr = bytesNeeded;
1683 for (i = 0; i < sizeof(reason_map) / sizeof(reason_map[0]); i++)
1684 {
1685 if (reasonFlags->pbData[0] & reason_map[i].reasonBit)
1686 {
1687 strcpyW(str, reason_map[i].reason);
1688 str += strlenW(reason_map[i].reason);
1689 if (i < sizeof(reason_map) / sizeof(reason_map[0]) - 1 &&
1690 numReasons)
1691 {
1692 strcpyW(str, sep);
1693 str += strlenW(sep);
1694 }
1695 }
1696 }
1697 strcpyW(str, bits);
1698 }
1699 return ret;
1700}
1701
1702static WCHAR crlDistPoint[MAX_STRING_RESOURCE_LEN];
1703static WCHAR distPointName[MAX_STRING_RESOURCE_LEN];
1704static WCHAR fullName[MAX_STRING_RESOURCE_LEN];
1705static WCHAR rdnName[MAX_STRING_RESOURCE_LEN];
1706static WCHAR reason[MAX_STRING_RESOURCE_LEN];
1707static WCHAR issuer[MAX_STRING_RESOURCE_LEN];
1708
1709static BOOL WINAPI CRYPT_FormatCRLDistPoints(DWORD dwCertEncodingType,
1710 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1711 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1712 DWORD *pcbFormat)
1713{
1714 CRL_DIST_POINTS_INFO *info;
1715 DWORD size;
1716 BOOL ret = FALSE;
1717
1718 if (!cbEncoded)
1719 {
1720 SetLastError(E_INVALIDARG);
1721 return FALSE;
1722 }
1723 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CRL_DIST_POINTS,
1724 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)) != FALSE)
1725 {
1726 static const WCHAR numFmt[] = { '%','d',0 };
1727 static const WCHAR colon[] = { ':',0 };
1728 static BOOL stringsLoaded = FALSE;
1729 DWORD bytesNeeded = sizeof(WCHAR); /* space for NULL terminator */
1730 BOOL haveAnEntry = FALSE;
1731 LPCWSTR headingSep, nameSep;
1732 WCHAR distPointNum[11];
1733 DWORD i;
1734
1735 if (!stringsLoaded)
1736 {
1737 LoadStringW(hInstance, IDS_CRL_DIST_POINT, crlDistPoint,
1738 sizeof(crlDistPoint) / sizeof(crlDistPoint[0]));
1739 LoadStringW(hInstance, IDS_CRL_DIST_POINT_NAME, distPointName,
1740 sizeof(distPointName) / sizeof(distPointName[0]));
1741 LoadStringW(hInstance, IDS_CRL_DIST_POINT_FULL_NAME, fullName,
1742 sizeof(fullName) / sizeof(fullName[0]));
1743 LoadStringW(hInstance, IDS_CRL_DIST_POINT_RDN_NAME, rdnName,
1744 sizeof(rdnName) / sizeof(rdnName[0]));
1745 LoadStringW(hInstance, IDS_CRL_DIST_POINT_REASON, reason,
1746 sizeof(reason) / sizeof(reason[0]));
1747 LoadStringW(hInstance, IDS_CRL_DIST_POINT_ISSUER, issuer,
1748 sizeof(issuer) / sizeof(issuer[0]));
1749 stringsLoaded = TRUE;
1750 }
1751 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1752 {
1753 headingSep = crlf;
1754 nameSep = colonCrlf;
1755 }
1756 else
1757 {
1758 headingSep = colonSep;
1759 nameSep = colon;
1760 }
1761
1762 for (i = 0; ret && i < info->cDistPoint; i++)
1763 {
1764 CRL_DIST_POINT *distPoint = &info->rgDistPoint[i];
1765
1766 if (distPoint->DistPointName.dwDistPointNameChoice !=
1767 CRL_DIST_POINT_NO_NAME)
1768 {
1769 bytesNeeded += strlenW(distPointName) * sizeof(WCHAR);
1770 bytesNeeded += strlenW(nameSep) * sizeof(WCHAR);
1771 if (distPoint->DistPointName.dwDistPointNameChoice ==
1772 CRL_DIST_POINT_FULL_NAME)
1773 bytesNeeded += strlenW(fullName) * sizeof(WCHAR);
1774 else
1775 bytesNeeded += strlenW(rdnName) * sizeof(WCHAR);
1776 bytesNeeded += strlenW(nameSep) * sizeof(WCHAR);
1777 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1778 bytesNeeded += 2 * strlenW(indent) * sizeof(WCHAR);
1779 /* The indent level (3) is higher than when used as the issuer,
1780 * because the name is subordinate to the name type (full vs.
1781 * RDN.)
1782 */
1783 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 3,
1784 &distPoint->DistPointName.u.FullName, NULL, &size);
1785 if (ret)
1786 bytesNeeded += size - sizeof(WCHAR);
1787 haveAnEntry = TRUE;
1788 }
1789 else if (distPoint->ReasonFlags.cbData)
1790 {
1791 bytesNeeded += strlenW(reason) * sizeof(WCHAR);
1792 ret = CRYPT_FormatReason(dwFormatStrType,
1793 &distPoint->ReasonFlags, NULL, &size);
1794 if (ret)
1795 bytesNeeded += size - sizeof(WCHAR);
1796 haveAnEntry = TRUE;
1797 }
1798 else if (distPoint->CRLIssuer.cAltEntry)
1799 {
1800 bytesNeeded += strlenW(issuer) * sizeof(WCHAR);
1801 bytesNeeded += strlenW(nameSep) * sizeof(WCHAR);
1802 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 2,
1803 &distPoint->CRLIssuer, NULL, &size);
1804 if (ret)
1805 bytesNeeded += size - sizeof(WCHAR);
1806 haveAnEntry = TRUE;
1807 }
1808 if (haveAnEntry)
1809 {
1810 bytesNeeded += sizeof(WCHAR); /* left bracket */
1811 sprintfW(distPointNum, numFmt, i + 1);
1812 bytesNeeded += strlenW(distPointNum) * sizeof(WCHAR);
1813 bytesNeeded += sizeof(WCHAR); /* right bracket */
1814 bytesNeeded += strlenW(crlDistPoint) * sizeof(WCHAR);
1815 bytesNeeded += strlenW(headingSep) * sizeof(WCHAR);
1816 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1817 bytesNeeded += strlenW(indent) * sizeof(WCHAR);
1818 }
1819 }
1820 if (!haveAnEntry)
1821 {
1822 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
1823
1824 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable,
1825 sizeof(infoNotAvailable) / sizeof(infoNotAvailable[0]));
1826 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR);
1827 if (!pbFormat)
1828 *pcbFormat = bytesNeeded;
1829 else if (*pcbFormat < bytesNeeded)
1830 {
1831 *pcbFormat = bytesNeeded;
1832 SetLastError(ERROR_MORE_DATA);
1833 ret = FALSE;
1834 }
1835 else
1836 {
1837 *pcbFormat = bytesNeeded;
1838 strcpyW((LPWSTR)pbFormat, infoNotAvailable);
1839 }
1840 }
1841 else
1842 {
1843 if (!pbFormat)
1844 *pcbFormat = bytesNeeded;
1845 else if (*pcbFormat < bytesNeeded)
1846 {
1847 *pcbFormat = bytesNeeded;
1848 SetLastError(ERROR_MORE_DATA);
1849 ret = FALSE;
1850 }
1851 else
1852 {
1853 LPWSTR str = pbFormat;
1854
1855 *pcbFormat = bytesNeeded;
1856 for (i = 0; ret && i < info->cDistPoint; i++)
1857 {
1858 CRL_DIST_POINT *distPoint = &info->rgDistPoint[i];
1859
1860 *str++ = '[';
1861 sprintfW(distPointNum, numFmt, i + 1);
1862 strcpyW(str, distPointNum);
1863 str += strlenW(distPointNum);
1864 *str++ = ']';
1865 strcpyW(str, crlDistPoint);
1866 str += strlenW(crlDistPoint);
1867 strcpyW(str, headingSep);
1868 str += strlenW(headingSep);
1869 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1870 {
1871 strcpyW(str, indent);
1872 str += strlenW(indent);
1873 }
1874 if (distPoint->DistPointName.dwDistPointNameChoice !=
1875 CRL_DIST_POINT_NO_NAME)
1876 {
1877 DWORD altNameSize = bytesNeeded;
1878
1879 strcpyW(str, distPointName);
1880 str += strlenW(distPointName);
1881 strcpyW(str, nameSep);
1882 str += strlenW(nameSep);
1883 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1884 {
1885 strcpyW(str, indent);
1886 str += strlenW(indent);
1887 strcpyW(str, indent);
1888 str += strlenW(indent);
1889 }
1890 if (distPoint->DistPointName.dwDistPointNameChoice ==
1891 CRL_DIST_POINT_FULL_NAME)
1892 {
1893 strcpyW(str, fullName);
1894 str += strlenW(fullName);
1895 }
1896 else
1897 {
1898 strcpyW(str, rdnName);
1899 str += strlenW(rdnName);
1900 }
1901 strcpyW(str, nameSep);
1902 str += strlenW(nameSep);
1903 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 3,
1904 &distPoint->DistPointName.u.FullName, str,
1905 &altNameSize);
1906 if (ret)
1907 str += altNameSize / sizeof(WCHAR) - 1;
1908 }
1909 else if (distPoint->ReasonFlags.cbData)
1910 {
1911 DWORD reasonSize = bytesNeeded;
1912
1913 strcpyW(str, reason);
1914 str += strlenW(reason);
1915 ret = CRYPT_FormatReason(dwFormatStrType,
1916 &distPoint->ReasonFlags, str, &reasonSize);
1917 if (ret)
1918 str += reasonSize / sizeof(WCHAR) - 1;
1919 }
1920 else if (distPoint->CRLIssuer.cAltEntry)
1921 {
1922 DWORD crlIssuerSize = bytesNeeded;
1923
1924 strcpyW(str, issuer);
1925 str += strlenW(issuer);
1926 strcpyW(str, nameSep);
1927 str += strlenW(nameSep);
1928 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 2,
1929 &distPoint->CRLIssuer, str,
1930 &crlIssuerSize);
1931 if (ret)
1932 str += crlIssuerSize / sizeof(WCHAR) - 1;
1933 }
1934 }
1935 }
1936 }
1937 LocalFree((HANDLE)info);
1938 }
1939 return ret;
1940}
1941
1942static BOOL WINAPI CRYPT_FormatEnhancedKeyUsage(DWORD dwCertEncodingType,
1943 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1944 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1945 DWORD *pcbFormat)
1946{
1947 CERT_ENHKEY_USAGE *usage;
1948 DWORD size;
1949 BOOL ret = FALSE;
1950
1951 if (!cbEncoded)
1952 {
1953 SetLastError(E_INVALIDARG);
1954 return FALSE;
1955 }
1956 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_ENHANCED_KEY_USAGE,
1957 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &usage, &size)) != FALSE)
1958 {
1959 WCHAR unknown[MAX_STRING_RESOURCE_LEN];
1960 DWORD i;
1961 DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */
1962 LPCWSTR sep;
1963 DWORD sepLen;
1964
1965 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1966 {
1967 sep = crlf;
1968 sepLen = strlenW(crlf) * sizeof(WCHAR);
1969 }
1970 else
1971 {
1972 sep = commaSpace;
1973 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
1974 }
1975
1976 LoadStringW(hInstance, IDS_USAGE_UNKNOWN, unknown,
1977 sizeof(unknown) / sizeof(unknown[0]));
1978 for (i = 0; i < usage->cUsageIdentifier; i++)
1979 {
1980 PCCRYPT_OID_INFO info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY,
1981 usage->rgpszUsageIdentifier[i], CRYPT_ENHKEY_USAGE_OID_GROUP_ID);
1982
1983 if (info)
1984 bytesNeeded += strlenW(info->pwszName) * sizeof(WCHAR);
1985 else
1986 bytesNeeded += strlenW(unknown) * sizeof(WCHAR);
1987 bytesNeeded += sizeof(WCHAR); /* space */
1988 bytesNeeded += sizeof(WCHAR); /* left paren */
1989 bytesNeeded += strlen(usage->rgpszUsageIdentifier[i]) *
1990 sizeof(WCHAR);
1991 bytesNeeded += sizeof(WCHAR); /* right paren */
1992 if (i < usage->cUsageIdentifier - 1)
1993 bytesNeeded += sepLen;
1994 }
1995 if (!pbFormat)
1996 *pcbFormat = bytesNeeded;
1997 else if (*pcbFormat < bytesNeeded)
1998 {
1999 *pcbFormat = bytesNeeded;
2000 SetLastError(ERROR_MORE_DATA);
2001 ret = FALSE;
2002 }
2003 else
2004 {
2005 LPWSTR str = pbFormat;
2006
2007 *pcbFormat = bytesNeeded;
2008 for (i = 0; i < usage->cUsageIdentifier; i++)
2009 {
2010 PCCRYPT_OID_INFO info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY,
2011 usage->rgpszUsageIdentifier[i],
2012 CRYPT_ENHKEY_USAGE_OID_GROUP_ID);
2013 LPCSTR oidPtr;
2014
2015 if (info)
2016 {
2017 strcpyW(str, info->pwszName);
2018 str += strlenW(info->pwszName);
2019 }
2020 else
2021 {
2022 strcpyW(str, unknown);
2023 str += strlenW(unknown);
2024 }
2025 *str++ = ' ';
2026 *str++ = '(';
2027 for (oidPtr = usage->rgpszUsageIdentifier[i]; *oidPtr; oidPtr++)
2028 *str++ = *oidPtr;
2029 *str++ = ')';
2030 *str = 0;
2031 if (i < usage->cUsageIdentifier - 1)
2032 {
2033 strcpyW(str, sep);
2034 str += sepLen / sizeof(WCHAR);
2035 }
2036 }
2037 }
2038 LocalFree((HANDLE)usage);
2039 }
2040 return ret;
2041}
2042
2043static struct BitToString netscapeCertTypeMap[] = {
2044 { NETSCAPE_SSL_CLIENT_AUTH_CERT_TYPE, IDS_NETSCAPE_SSL_CLIENT, { 0 } },
2045 { NETSCAPE_SSL_SERVER_AUTH_CERT_TYPE, IDS_NETSCAPE_SSL_SERVER, { 0 } },
2046 { NETSCAPE_SMIME_CERT_TYPE, IDS_NETSCAPE_SMIME, { 0 } },
2047 { NETSCAPE_SIGN_CERT_TYPE, IDS_NETSCAPE_SIGN, { 0 } },
2048 { NETSCAPE_SSL_CA_CERT_TYPE, IDS_NETSCAPE_SSL_CA, { 0 } },
2049 { NETSCAPE_SMIME_CA_CERT_TYPE, IDS_NETSCAPE_SMIME_CA, { 0 } },
2050 { NETSCAPE_SIGN_CA_CERT_TYPE, IDS_NETSCAPE_SIGN_CA, { 0 } },
2051};
2052
2053static BOOL WINAPI CRYPT_FormatNetscapeCertType(DWORD dwCertEncodingType,
2054 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
2055 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
2056 DWORD *pcbFormat)
2057{
2058 DWORD size;
2059 CRYPT_BIT_BLOB *bits;
2060 BOOL ret;
2061
2062 if (!cbEncoded)
2063 {
2064 SetLastError(E_INVALIDARG);
2065 return FALSE;
2066 }
2067 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_BITS,
2068 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &bits, &size)) != FALSE)
2069 {
2070 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
2071 DWORD bytesNeeded = sizeof(WCHAR);
2072
2073 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable,
2074 sizeof(infoNotAvailable) / sizeof(infoNotAvailable[0]));
2075 if (!bits->cbData || bits->cbData > 1)
2076 {
2077 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR);
2078 if (!pbFormat)
2079 *pcbFormat = bytesNeeded;
2080 else if (*pcbFormat < bytesNeeded)
2081 {
2082 *pcbFormat = bytesNeeded;
2083 SetLastError(ERROR_MORE_DATA);
2084 ret = FALSE;
2085 }
2086 else
2087 {
2088 LPWSTR str = pbFormat;
2089
2090 *pcbFormat = bytesNeeded;
2091 strcpyW(str, infoNotAvailable);
2092 }
2093 }
2094 else
2095 {
2096 static BOOL stringsLoaded = FALSE;
2097 int i;
2098 DWORD bitStringLen;
2099 BOOL first = TRUE;
2100
2101 if (!stringsLoaded)
2102 {
2103 for (i = 0; i < sizeof(netscapeCertTypeMap) /
2104 sizeof(netscapeCertTypeMap[0]); i++)
2105 LoadStringW(hInstance, netscapeCertTypeMap[i].id,
2106 netscapeCertTypeMap[i].str, MAX_STRING_RESOURCE_LEN);
2107 stringsLoaded = TRUE;
2108 }
2109 CRYPT_FormatBits(bits->pbData[0], netscapeCertTypeMap,
2110 sizeof(netscapeCertTypeMap) / sizeof(netscapeCertTypeMap[0]),
2111 NULL, &bitStringLen, &first);
2112 bytesNeeded += bitStringLen;
2113 bytesNeeded += 3 * sizeof(WCHAR); /* " (" + ")" */
2114 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData,
2115 bits->cbData, NULL, &size);
2116 bytesNeeded += size;
2117 if (!pbFormat)
2118 *pcbFormat = bytesNeeded;
2119 else if (*pcbFormat < bytesNeeded)
2120 {
2121 *pcbFormat = bytesNeeded;
2122 SetLastError(ERROR_MORE_DATA);
2123 ret = FALSE;
2124 }
2125 else
2126 {
2127 LPWSTR str = pbFormat;
2128
2129 bitStringLen = bytesNeeded;
2130 first = TRUE;
2131 CRYPT_FormatBits(bits->pbData[0], netscapeCertTypeMap,
2132 sizeof(netscapeCertTypeMap) / sizeof(netscapeCertTypeMap[0]),
2133 str, &bitStringLen, &first);
2134 str += bitStringLen / sizeof(WCHAR) - 1;
2135 *str++ = ' ';
2136 *str++ = '(';
2137 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData,
2138 bits->cbData, str, &size);
2139 str += size / sizeof(WCHAR) - 1;
2140 *str++ = ')';
2141 *str = 0;
2142 }
2143 }
2144 LocalFree((HANDLE)bits);
2145 }
2146 return ret;
2147}
2148
2149static WCHAR financialCriteria[MAX_STRING_RESOURCE_LEN];
2150static WCHAR available[MAX_STRING_RESOURCE_LEN];
2151static WCHAR notAvailable[MAX_STRING_RESOURCE_LEN];
2152static WCHAR meetsCriteria[MAX_STRING_RESOURCE_LEN];
2153static WCHAR yes[MAX_STRING_RESOURCE_LEN];
2154static WCHAR no[MAX_STRING_RESOURCE_LEN];
2155
2156static BOOL WINAPI CRYPT_FormatSpcFinancialCriteria(DWORD dwCertEncodingType,
2157 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
2158 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
2159 DWORD *pcbFormat)
2160{
2161 SPC_FINANCIAL_CRITERIA criteria;
2162 DWORD size = sizeof(criteria);
2163 BOOL ret = FALSE;
2164
2165 if (!cbEncoded)
2166 {
2167 SetLastError(E_INVALIDARG);
2168 return FALSE;
2169 }
2170 if ((ret = CryptDecodeObjectEx(dwCertEncodingType,
2171 SPC_FINANCIAL_CRITERIA_STRUCT, pbEncoded, cbEncoded, 0, NULL, &criteria,
2172 &size)) != FALSE)
2173 {
2174 static BOOL stringsLoaded = FALSE;
2175 DWORD bytesNeeded = sizeof(WCHAR);
2176 LPCWSTR sep;
2177 DWORD sepLen;
2178
2179 if (!stringsLoaded)
2180 {
2181 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA, financialCriteria,
2182 sizeof(financialCriteria) / sizeof(financialCriteria[0]));
2183 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_AVAILABLE, available,
2184 sizeof(available) / sizeof(available[0]));
2185 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_NOT_AVAILABLE,
2186 notAvailable, sizeof(notAvailable) / sizeof(notAvailable[0]));
2187 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_MEETS_CRITERIA,
2188 meetsCriteria, sizeof(meetsCriteria) / sizeof(meetsCriteria[0]));
2189 LoadStringW(hInstance, IDS_YES, yes, sizeof(yes) / sizeof(yes[0]));
2190 LoadStringW(hInstance, IDS_NO, no, sizeof(no) / sizeof(no[0]));
2191 stringsLoaded = TRUE;
2192 }
2193 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
2194 {
2195 sep = crlf;
2196 sepLen = strlenW(crlf) * sizeof(WCHAR);
2197 }
2198 else
2199 {
2200 sep = commaSpace;
2201 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
2202 }
2203 bytesNeeded += strlenW(financialCriteria) * sizeof(WCHAR);
2204 if (criteria.fFinancialInfoAvailable)
2205 {
2206 bytesNeeded += strlenW(available) * sizeof(WCHAR);
2207 bytesNeeded += sepLen;
2208 bytesNeeded += strlenW(meetsCriteria) * sizeof(WCHAR);
2209 if (criteria.fMeetsCriteria)
2210 bytesNeeded += strlenW(yes) * sizeof(WCHAR);
2211 else
2212 bytesNeeded += strlenW(no) * sizeof(WCHAR);
2213 }
2214 else
2215 bytesNeeded += strlenW(notAvailable) * sizeof(WCHAR);
2216 if (!pbFormat)
2217 *pcbFormat = bytesNeeded;
2218 else if (*pcbFormat < bytesNeeded)
2219 {
2220 *pcbFormat = bytesNeeded;
2221 SetLastError(ERROR_MORE_DATA);
2222 ret = FALSE;
2223 }
2224 else
2225 {
2226 LPWSTR str = pbFormat;
2227
2228 *pcbFormat = bytesNeeded;
2229 strcpyW(str, financialCriteria);
2230 str += strlenW(financialCriteria);
2231 if (criteria.fFinancialInfoAvailable)
2232 {
2233 strcpyW(str, available);
2234 str += strlenW(available);
2235 strcpyW(str, sep);
2236 str += sepLen / sizeof(WCHAR);
2237 strcpyW(str, meetsCriteria);
2238 str += strlenW(meetsCriteria);
2239 if (criteria.fMeetsCriteria)
2240 strcpyW(str, yes);
2241 else
2242 strcpyW(str, no);
2243 }
2244 else
2245 {
2246 strcpyW(str, notAvailable);
2247 str += strlenW(notAvailable);
2248 }
2249 }
2250 }
2251 return ret;
2252}
2253
2254static BOOL WINAPI CRYPT_FormatUnicodeString(DWORD dwCertEncodingType,
2255 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
2256 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
2257 DWORD *pcbFormat)
2258{
2259 CERT_NAME_VALUE *value;
2260 DWORD size;
2261 BOOL ret;
2262
2263 if (!cbEncoded)
2264 {
2265 SetLastError(E_INVALIDARG);
2266 return FALSE;
2267 }
2268 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_UNICODE_ANY_STRING,
2269 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &value, &size)) != FALSE)
2270 {
2271 if (!pbFormat)
2272 *pcbFormat = value->Value.cbData;
2273 else if (*pcbFormat < value->Value.cbData)
2274 {
2275 *pcbFormat = value->Value.cbData;
2276 SetLastError(ERROR_MORE_DATA);
2277 ret = FALSE;
2278 }
2279 else
2280 {
2281 LPWSTR str = pbFormat;
2282
2283 *pcbFormat = value->Value.cbData;
2284 strcpyW(str, (LPWSTR)value->Value.pbData);
2285 }
2286 }
2287 return ret;
2288}
2289
2290typedef BOOL (*WINAPI CryptFormatObjectFunc)(DWORD, DWORD, DWORD, void *,
2291 LPCSTR, const BYTE *, DWORD, void *, DWORD *);
2292
2293static CryptFormatObjectFunc CRYPT_GetBuiltinFormatFunction(DWORD encodingType,
2294 DWORD formatStrType, LPCSTR lpszStructType)
2295{
2296 CryptFormatObjectFunc format = NULL;
2297
2298 if ((encodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING)
2299 {
2300 SetLastError(ERROR_FILE_NOT_FOUND);
2301 return NULL;
2302 }
2303 if (!HIWORD(lpszStructType))
2304 {
2305 switch (LOWORD(lpszStructType))
2306 {
2307 case LOWORD(X509_KEY_USAGE):
2308 format = CRYPT_FormatKeyUsage;
2309 break;
2310 case LOWORD(X509_ALTERNATE_NAME):
2311 format = CRYPT_FormatAltName;
2312 break;
2313 case LOWORD(X509_BASIC_CONSTRAINTS2):
2314 format = CRYPT_FormatBasicConstraints2;
2315 break;
2316 case LOWORD(X509_AUTHORITY_KEY_ID2):
2317 format = CRYPT_FormatAuthorityKeyId2;
2318 break;
2319 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
2320 format = CRYPT_FormatAuthorityInfoAccess;
2321 break;
2322 case LOWORD(X509_CRL_DIST_POINTS):
2323 format = CRYPT_FormatCRLDistPoints;
2324 break;
2325 case LOWORD(X509_ENHANCED_KEY_USAGE):
2326 format = CRYPT_FormatEnhancedKeyUsage;
2327 break;
2328 case LOWORD(SPC_FINANCIAL_CRITERIA_STRUCT):
2329 format = CRYPT_FormatSpcFinancialCriteria;
2330 break;
2331 }
2332 }
2333 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
2334 format = CRYPT_FormatAltName;
2335 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
2336 format = CRYPT_FormatAltName;
2337 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
2338 format = CRYPT_FormatKeyUsage;
2339 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
2340 format = CRYPT_FormatAltName;
2341 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
2342 format = CRYPT_FormatAltName;
2343 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
2344 format = CRYPT_FormatBasicConstraints2;
2345 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
2346 format = CRYPT_FormatAuthorityInfoAccess;
2347 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
2348 format = CRYPT_FormatAuthorityKeyId2;
2349 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
2350 format = CRYPT_FormatCRLDistPoints;
2351 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
2352 format = CRYPT_FormatEnhancedKeyUsage;
2353 else if (!strcmp(lpszStructType, szOID_NETSCAPE_CERT_TYPE))
2354 format = CRYPT_FormatNetscapeCertType;
2355 else if (!strcmp(lpszStructType, szOID_NETSCAPE_BASE_URL) ||
2356 !strcmp(lpszStructType, szOID_NETSCAPE_REVOCATION_URL) ||
2357 !strcmp(lpszStructType, szOID_NETSCAPE_CA_REVOCATION_URL) ||
2358 !strcmp(lpszStructType, szOID_NETSCAPE_CERT_RENEWAL_URL) ||
2359 !strcmp(lpszStructType, szOID_NETSCAPE_CA_POLICY_URL) ||
2360 !strcmp(lpszStructType, szOID_NETSCAPE_SSL_SERVER_NAME) ||
2361 !strcmp(lpszStructType, szOID_NETSCAPE_COMMENT))
2362 format = CRYPT_FormatUnicodeString;
2363 else if (!strcmp(lpszStructType, SPC_FINANCIAL_CRITERIA_OBJID))
2364 format = CRYPT_FormatSpcFinancialCriteria;
2365 return format;
2366}
2367
2368BOOL WINAPI CryptFormatObject(DWORD dwCertEncodingType, DWORD dwFormatType,
2369 DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType,
2370 const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, DWORD *pcbFormat)
2371{
2372 CryptFormatObjectFunc format = NULL;
2373 HCRYPTOIDFUNCADDR hFunc = NULL;
2374 BOOL ret = FALSE;
2375
2376 TRACE("(%08x, %d, %08x, %p, %s, %p, %d, %p, %p)\n", dwCertEncodingType,
2377 dwFormatType, dwFormatStrType, pFormatStruct, debugstr_a(lpszStructType),
2378 pbEncoded, cbEncoded, pbFormat, pcbFormat);
2379
2380 if (!(format = CRYPT_GetBuiltinFormatFunction(dwCertEncodingType,
2381 dwFormatStrType, lpszStructType)))
2382 {
2383 static HCRYPTOIDFUNCSET set = NULL;
2384
2385 if (!set)
2386 set = CryptInitOIDFunctionSet(CRYPT_OID_FORMAT_OBJECT_FUNC, 0);
2387 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
2388 (void **)&format, &hFunc);
2389 }
2390 if (!format && (dwCertEncodingType & CERT_ENCODING_TYPE_MASK) ==
2391 X509_ASN_ENCODING && !(dwFormatStrType & CRYPT_FORMAT_STR_NO_HEX))
2392 format = CRYPT_FormatHexString;
2393 if (format)
2394 ret = format(dwCertEncodingType, dwFormatType, dwFormatStrType,
2395 pFormatStruct, lpszStructType, pbEncoded, cbEncoded, pbFormat,
2396 pcbFormat);
2397 if (hFunc)
2398 CryptFreeOIDFunctionAddress(hFunc, 0);
2399 return ret;
2400}
Note: See TracBrowser for help on using the repository browser.