2 * crypt32 Crypt*Object functions
4 * Copyright 2007 Juan Lang
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.
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.
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
21 #define NONAMELESSUNION
28 #include "crypt32_private.h"
30 #include "wine/unicode.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
35 static BOOL
CRYPT_ReadBlobFromFile(LPCWSTR fileName
, PCERT_BLOB blob
)
40 TRACE("%s\n", debugstr_w(fileName
));
42 file
= CreateFileW(fileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
43 OPEN_EXISTING
, 0, NULL
);
44 if (file
!= INVALID_HANDLE_VALUE
)
47 blob
->cbData
= GetFileSize(file
, NULL
);
50 blob
->pbData
= CryptMemAlloc(blob
->cbData
);
55 ret
= ReadFile(file
, blob
->pbData
, blob
->cbData
, &read
, NULL
);
60 TRACE("returning %d\n", ret
);
64 static BOOL
CRYPT_QueryContextBlob(const CERT_BLOB
*blob
,
65 DWORD dwExpectedContentTypeFlags
, HCERTSTORE store
,
66 DWORD
*contentType
, const void **ppvContext
)
70 if (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CERT
)
72 ret
= pCertInterface
->addEncodedToStore(store
, X509_ASN_ENCODING
,
73 blob
->pbData
, blob
->cbData
, CERT_STORE_ADD_ALWAYS
, ppvContext
);
74 if (ret
&& contentType
)
75 *contentType
= CERT_QUERY_CONTENT_CERT
;
77 if (!ret
&& (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CRL
))
79 ret
= pCRLInterface
->addEncodedToStore(store
, X509_ASN_ENCODING
,
80 blob
->pbData
, blob
->cbData
, CERT_STORE_ADD_ALWAYS
, ppvContext
);
81 if (ret
&& contentType
)
82 *contentType
= CERT_QUERY_CONTENT_CRL
;
84 if (!ret
&& (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CTL
))
86 ret
= pCTLInterface
->addEncodedToStore(store
, X509_ASN_ENCODING
,
87 blob
->pbData
, blob
->cbData
, CERT_STORE_ADD_ALWAYS
, ppvContext
);
88 if (ret
&& contentType
)
89 *contentType
= CERT_QUERY_CONTENT_CTL
;
94 static BOOL
CRYPT_QueryContextObject(DWORD dwObjectType
, const void *pvObject
,
95 DWORD dwExpectedContentTypeFlags
, DWORD dwExpectedFormatTypeFlags
,
96 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
, DWORD
*pdwFormatType
,
97 HCERTSTORE
*phCertStore
, const void **ppvContext
)
100 const CERT_BLOB
*blob
;
103 DWORD formatType
= 0;
105 switch (dwObjectType
)
107 case CERT_QUERY_OBJECT_FILE
:
108 /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so
109 * just read the file directly
111 ret
= CRYPT_ReadBlobFromFile((LPCWSTR
)pvObject
, &fileBlob
);
114 case CERT_QUERY_OBJECT_BLOB
:
115 blob
= (const CERT_BLOB
*)pvObject
;
119 SetLastError(E_INVALIDARG
); /* FIXME: is this the correct error? */
126 store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
127 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
128 if (dwExpectedFormatTypeFlags
& CERT_QUERY_FORMAT_FLAG_BINARY
)
130 ret
= CRYPT_QueryContextBlob(blob
, dwExpectedContentTypeFlags
, store
,
131 pdwContentType
, ppvContext
);
133 formatType
= CERT_QUERY_FORMAT_BINARY
;
136 (dwExpectedFormatTypeFlags
& CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED
))
138 CRYPT_DATA_BLOB trimmed
= { blob
->cbData
, blob
->pbData
};
139 CRYPT_DATA_BLOB decoded
;
141 while (trimmed
.cbData
&& !trimmed
.pbData
[trimmed
.cbData
- 1])
143 ret
= CryptStringToBinaryA((LPSTR
)trimmed
.pbData
, trimmed
.cbData
,
144 CRYPT_STRING_BASE64_ANY
, NULL
, &decoded
.cbData
, NULL
, NULL
);
147 decoded
.pbData
= CryptMemAlloc(decoded
.cbData
);
150 ret
= CryptStringToBinaryA((LPSTR
)trimmed
.pbData
,
151 trimmed
.cbData
, CRYPT_STRING_BASE64_ANY
, decoded
.pbData
,
152 &decoded
.cbData
, NULL
, NULL
);
155 ret
= CRYPT_QueryContextBlob(&decoded
,
156 dwExpectedContentTypeFlags
, store
, pdwContentType
,
159 formatType
= CERT_QUERY_FORMAT_BASE64_ENCODED
;
161 CryptMemFree(decoded
.pbData
);
169 if (pdwMsgAndCertEncodingType
)
170 *pdwMsgAndCertEncodingType
= X509_ASN_ENCODING
;
172 *pdwFormatType
= formatType
;
174 *phCertStore
= CertDuplicateStore(store
);
176 CertCloseStore(store
, 0);
177 if (blob
== &fileBlob
)
178 CryptMemFree(blob
->pbData
);
179 TRACE("returning %d\n", ret
);
183 static BOOL
CRYPT_QuerySerializedContextObject(DWORD dwObjectType
,
184 const void *pvObject
, DWORD dwExpectedContentTypeFlags
,
185 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
186 HCERTSTORE
*phCertStore
, const void **ppvContext
)
189 const CERT_BLOB
*blob
;
190 const WINE_CONTEXT_INTERFACE
*contextInterface
= NULL
;
195 switch (dwObjectType
)
197 case CERT_QUERY_OBJECT_FILE
:
198 /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so
199 * just read the file directly
201 ret
= CRYPT_ReadBlobFromFile((LPCWSTR
)pvObject
, &fileBlob
);
204 case CERT_QUERY_OBJECT_BLOB
:
205 blob
= (const CERT_BLOB
*)pvObject
;
209 SetLastError(E_INVALIDARG
); /* FIXME: is this the correct error? */
216 context
= CRYPT_ReadSerializedElement(blob
->pbData
, blob
->cbData
,
217 CERT_STORE_ALL_CONTEXT_FLAG
, &contextType
);
220 DWORD contentType
, certStoreOffset
;
225 case CERT_STORE_CERTIFICATE_CONTEXT
:
226 contextInterface
= pCertInterface
;
227 contentType
= CERT_QUERY_CONTENT_SERIALIZED_CERT
;
228 certStoreOffset
= offsetof(CERT_CONTEXT
, hCertStore
);
229 if (!(dwExpectedContentTypeFlags
&
230 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
))
232 SetLastError(ERROR_INVALID_DATA
);
237 case CERT_STORE_CRL_CONTEXT
:
238 contextInterface
= pCRLInterface
;
239 contentType
= CERT_QUERY_CONTENT_SERIALIZED_CRL
;
240 certStoreOffset
= offsetof(CRL_CONTEXT
, hCertStore
);
241 if (!(dwExpectedContentTypeFlags
&
242 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
))
244 SetLastError(ERROR_INVALID_DATA
);
249 case CERT_STORE_CTL_CONTEXT
:
250 contextInterface
= pCTLInterface
;
251 contentType
= CERT_QUERY_CONTENT_SERIALIZED_CTL
;
252 certStoreOffset
= offsetof(CTL_CONTEXT
, hCertStore
);
253 if (!(dwExpectedContentTypeFlags
&
254 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
))
256 SetLastError(ERROR_INVALID_DATA
);
262 SetLastError(ERROR_INVALID_DATA
);
266 if (pdwMsgAndCertEncodingType
)
267 *pdwMsgAndCertEncodingType
= X509_ASN_ENCODING
;
269 *pdwContentType
= contentType
;
271 *phCertStore
= CertDuplicateStore(
272 *(HCERTSTORE
*)((const BYTE
*)context
+ certStoreOffset
));
274 *ppvContext
= contextInterface
->duplicate(context
);
278 if (contextInterface
&& context
)
279 contextInterface
->free(context
);
280 if (blob
== &fileBlob
)
281 CryptMemFree(blob
->pbData
);
282 TRACE("returning %d\n", ret
);
286 static BOOL
CRYPT_QuerySerializedStoreObject(DWORD dwObjectType
,
287 const void *pvObject
, DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
288 HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
)
290 LPCWSTR fileName
= (LPCWSTR
)pvObject
;
294 if (dwObjectType
!= CERT_QUERY_OBJECT_FILE
)
296 FIXME("unimplemented for non-file type %d\n", dwObjectType
);
297 SetLastError(E_INVALIDARG
); /* FIXME: is this the correct error? */
300 TRACE("%s\n", debugstr_w(fileName
));
301 file
= CreateFileW(fileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
302 OPEN_EXISTING
, 0, NULL
);
303 if (file
!= INVALID_HANDLE_VALUE
)
305 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
306 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
308 ret
= CRYPT_ReadSerializedStoreFromFile(file
, store
);
311 if (pdwMsgAndCertEncodingType
)
312 *pdwMsgAndCertEncodingType
= X509_ASN_ENCODING
;
314 *pdwContentType
= CERT_QUERY_CONTENT_SERIALIZED_STORE
;
316 *phCertStore
= CertDuplicateStore(store
);
318 CertCloseStore(store
, 0);
321 TRACE("returning %d\n", ret
);
325 /* Used to decode non-embedded messages */
326 static BOOL
CRYPT_QueryMessageObject(DWORD dwObjectType
, const void *pvObject
,
327 DWORD dwExpectedContentTypeFlags
, DWORD
*pdwMsgAndCertEncodingType
,
328 DWORD
*pdwContentType
, HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
)
331 const CERT_BLOB
*blob
;
333 HCRYPTMSG msg
= NULL
;
334 DWORD encodingType
= X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
;
336 switch (dwObjectType
)
338 case CERT_QUERY_OBJECT_FILE
:
339 /* This isn't an embedded PKCS7 message, so just read the file
342 ret
= CRYPT_ReadBlobFromFile((LPCWSTR
)pvObject
, &fileBlob
);
345 case CERT_QUERY_OBJECT_BLOB
:
346 blob
= (const CERT_BLOB
*)pvObject
;
350 SetLastError(E_INVALIDARG
); /* FIXME: is this the correct error? */
357 /* Try it first as a PKCS content info */
358 if ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
) ||
359 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
))
361 msg
= CryptMsgOpenToDecode(encodingType
, 0, 0, 0, NULL
, NULL
);
364 ret
= CryptMsgUpdate(msg
, blob
->pbData
, blob
->cbData
, TRUE
);
367 DWORD type
, len
= sizeof(type
);
369 ret
= CryptMsgGetParam(msg
, CMSG_TYPE_PARAM
, 0, &type
, &len
);
372 if ((dwExpectedContentTypeFlags
&
373 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
))
375 if (type
!= CMSG_SIGNED
)
377 SetLastError(ERROR_INVALID_DATA
);
380 else if (pdwContentType
)
381 *pdwContentType
= CERT_QUERY_CONTENT_PKCS7_SIGNED
;
383 else if ((dwExpectedContentTypeFlags
&
384 CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
))
386 if (type
!= CMSG_DATA
)
388 SetLastError(ERROR_INVALID_DATA
);
391 else if (pdwContentType
)
392 *pdwContentType
= CERT_QUERY_CONTENT_PKCS7_UNSIGNED
;
403 /* Failing that, try explicitly typed messages */
405 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
))
407 msg
= CryptMsgOpenToDecode(encodingType
, 0, CMSG_SIGNED
, 0, NULL
, NULL
);
410 ret
= CryptMsgUpdate(msg
, blob
->pbData
, blob
->cbData
, TRUE
);
417 if (msg
&& pdwContentType
)
418 *pdwContentType
= CERT_QUERY_CONTENT_PKCS7_SIGNED
;
421 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
))
423 msg
= CryptMsgOpenToDecode(encodingType
, 0, CMSG_DATA
, 0, NULL
, NULL
);
426 ret
= CryptMsgUpdate(msg
, blob
->pbData
, blob
->cbData
, TRUE
);
433 if (msg
&& pdwContentType
)
434 *pdwContentType
= CERT_QUERY_CONTENT_PKCS7_UNSIGNED
;
436 if (pdwMsgAndCertEncodingType
)
437 *pdwMsgAndCertEncodingType
= encodingType
;
443 *phCertStore
= CertOpenStore(CERT_STORE_PROV_MSG
, encodingType
, 0,
446 if (blob
== &fileBlob
)
447 CryptMemFree(blob
->pbData
);
448 TRACE("returning %d\n", ret
);
452 static BOOL
CRYPT_QueryEmbeddedMessageObject(DWORD dwObjectType
,
453 const void *pvObject
, DWORD dwExpectedContentTypeFlags
,
454 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
455 HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
)
461 TRACE("%s\n", debugstr_w((LPCWSTR
)pvObject
));
463 if (dwObjectType
!= CERT_QUERY_OBJECT_FILE
)
465 WARN("don't know what to do for type %d embedded signed messages\n",
467 SetLastError(E_INVALIDARG
);
470 file
= CreateFileW((LPCWSTR
)pvObject
, GENERIC_READ
, FILE_SHARE_READ
,
471 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
472 if (file
!= INVALID_HANDLE_VALUE
)
474 ret
= CryptSIPRetrieveSubjectGuid((LPCWSTR
)pvObject
, file
, &subject
);
477 SIP_DISPATCH_INFO sip
;
479 memset(&sip
, 0, sizeof(sip
));
480 sip
.cbSize
= sizeof(sip
);
481 ret
= CryptSIPLoad(&subject
, 0, &sip
);
484 SIP_SUBJECTINFO subjectInfo
;
488 memset(&subjectInfo
, 0, sizeof(subjectInfo
));
489 subjectInfo
.cbSize
= sizeof(subjectInfo
);
490 subjectInfo
.pgSubjectType
= &subject
;
491 subjectInfo
.hFile
= file
;
492 subjectInfo
.pwsFileName
= (LPCWSTR
)pvObject
;
493 ret
= sip
.pfGet(&subjectInfo
, &encodingType
, 0, &blob
.cbData
,
497 blob
.pbData
= CryptMemAlloc(blob
.cbData
);
500 ret
= sip
.pfGet(&subjectInfo
, &encodingType
, 0,
501 &blob
.cbData
, blob
.pbData
);
504 ret
= CRYPT_QueryMessageObject(
505 CERT_QUERY_OBJECT_BLOB
, &blob
,
506 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
,
507 pdwMsgAndCertEncodingType
, NULL
, phCertStore
,
509 if (ret
&& pdwContentType
)
511 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
;
513 CryptMemFree(blob
.pbData
);
517 SetLastError(ERROR_OUTOFMEMORY
);
525 TRACE("returning %d\n", ret
);
529 BOOL WINAPI
CryptQueryObject(DWORD dwObjectType
, const void *pvObject
,
530 DWORD dwExpectedContentTypeFlags
, DWORD dwExpectedFormatTypeFlags
,
531 DWORD dwFlags
, DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
532 DWORD
*pdwFormatType
, HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
,
533 const void **ppvContext
)
535 static const DWORD unimplementedTypes
=
536 CERT_QUERY_CONTENT_FLAG_PKCS10
| CERT_QUERY_CONTENT_FLAG_PFX
|
537 CERT_QUERY_CONTENT_FLAG_CERT_PAIR
;
540 TRACE("(%08x, %p, %08x, %08x, %08x, %p, %p, %p, %p, %p, %p)\n",
541 dwObjectType
, pvObject
, dwExpectedContentTypeFlags
,
542 dwExpectedFormatTypeFlags
, dwFlags
, pdwMsgAndCertEncodingType
,
543 pdwContentType
, pdwFormatType
, phCertStore
, phMsg
, ppvContext
);
545 if (dwObjectType
!= CERT_QUERY_OBJECT_BLOB
&&
546 dwObjectType
!= CERT_QUERY_OBJECT_FILE
)
548 WARN("unsupported type %d\n", dwObjectType
);
549 SetLastError(E_INVALIDARG
);
554 WARN("missing required argument\n");
555 SetLastError(E_INVALIDARG
);
558 if (dwExpectedContentTypeFlags
& unimplementedTypes
)
559 WARN("unimplemented for types %08x\n",
560 dwExpectedContentTypeFlags
& unimplementedTypes
);
563 *pdwFormatType
= CERT_QUERY_FORMAT_BINARY
;
572 if ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CERT
) ||
573 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CRL
) ||
574 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CTL
))
576 ret
= CRYPT_QueryContextObject(dwObjectType
, pvObject
,
577 dwExpectedContentTypeFlags
, dwExpectedFormatTypeFlags
,
578 pdwMsgAndCertEncodingType
, pdwContentType
, pdwFormatType
, phCertStore
,
582 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
))
584 ret
= CRYPT_QuerySerializedStoreObject(dwObjectType
, pvObject
,
585 pdwMsgAndCertEncodingType
, pdwContentType
, phCertStore
, phMsg
);
588 ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
) ||
589 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
) ||
590 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
)))
592 ret
= CRYPT_QuerySerializedContextObject(dwObjectType
, pvObject
,
593 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
594 phCertStore
, ppvContext
);
597 ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
) ||
598 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
)))
600 ret
= CRYPT_QueryMessageObject(dwObjectType
, pvObject
,
601 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
605 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED
))
607 ret
= CRYPT_QueryEmbeddedMessageObject(dwObjectType
, pvObject
,
608 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
612 SetLastError(CRYPT_E_NO_MATCH
);
613 TRACE("returning %d\n", ret
);
617 static BOOL WINAPI
CRYPT_FormatHexString(DWORD dwCertEncodingType
,
618 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
619 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
626 bytesNeeded
= (cbEncoded
* 3) * sizeof(WCHAR
);
628 bytesNeeded
= sizeof(WCHAR
);
631 *pcbFormat
= bytesNeeded
;
634 else if (*pcbFormat
< bytesNeeded
)
636 *pcbFormat
= bytesNeeded
;
637 SetLastError(ERROR_MORE_DATA
);
642 static const WCHAR fmt
[] = { '%','0','2','x',' ',0 };
643 static const WCHAR endFmt
[] = { '%','0','2','x',0 };
645 LPWSTR ptr
= pbFormat
;
647 *pcbFormat
= bytesNeeded
;
650 for (i
= 0; i
< cbEncoded
; i
++)
652 if (i
< cbEncoded
- 1)
653 ptr
+= sprintfW(ptr
, fmt
, pbEncoded
[i
]);
655 ptr
+= sprintfW(ptr
, endFmt
, pbEncoded
[i
]);
665 #define MAX_STRING_RESOURCE_LEN 128
667 static const WCHAR commaSpace
[] = { ',',' ',0 };
673 WCHAR str
[MAX_STRING_RESOURCE_LEN
];
676 static BOOL
CRYPT_FormatBits(BYTE bits
, const struct BitToString
*map
,
677 DWORD mapEntries
, void *pbFormat
, DWORD
*pcbFormat
, BOOL
*first
)
679 DWORD bytesNeeded
= sizeof(WCHAR
);
681 BOOL ret
= TRUE
, localFirst
= *first
;
683 for (i
= 0; i
< mapEntries
; i
++)
684 if (bits
& map
[i
].bit
)
687 bytesNeeded
+= strlenW(commaSpace
) * sizeof(WCHAR
);
689 bytesNeeded
+= strlenW(map
[i
].str
) * sizeof(WCHAR
);
694 *pcbFormat
= bytesNeeded
;
696 else if (*pcbFormat
< bytesNeeded
)
699 *pcbFormat
= bytesNeeded
;
700 SetLastError(ERROR_MORE_DATA
);
705 LPWSTR str
= pbFormat
;
708 *pcbFormat
= bytesNeeded
;
709 for (i
= 0; i
< mapEntries
; i
++)
710 if (bits
& map
[i
].bit
)
714 strcpyW(str
, commaSpace
);
715 str
+= strlenW(commaSpace
);
718 strcpyW(str
, map
[i
].str
);
719 str
+= strlenW(map
[i
].str
);
726 static struct BitToString keyUsageByte0Map
[] = {
727 { CERT_DIGITAL_SIGNATURE_KEY_USAGE
, IDS_DIGITAL_SIGNATURE
, { 0 } },
728 { CERT_NON_REPUDIATION_KEY_USAGE
, IDS_NON_REPUDIATION
, { 0 } },
729 { CERT_KEY_ENCIPHERMENT_KEY_USAGE
, IDS_KEY_ENCIPHERMENT
, { 0 } },
730 { CERT_DATA_ENCIPHERMENT_KEY_USAGE
, IDS_DATA_ENCIPHERMENT
, { 0 } },
731 { CERT_KEY_AGREEMENT_KEY_USAGE
, IDS_KEY_AGREEMENT
, { 0 } },
732 { CERT_KEY_CERT_SIGN_KEY_USAGE
, IDS_CERT_SIGN
, { 0 } },
733 { CERT_OFFLINE_CRL_SIGN_KEY_USAGE
, IDS_OFFLINE_CRL_SIGN
, { 0 } },
734 { CERT_CRL_SIGN_KEY_USAGE
, IDS_CRL_SIGN
, { 0 } },
735 { CERT_ENCIPHER_ONLY_KEY_USAGE
, IDS_ENCIPHER_ONLY
, { 0 } },
737 static struct BitToString keyUsageByte1Map
[] = {
738 { CERT_DECIPHER_ONLY_KEY_USAGE
, IDS_DECIPHER_ONLY
, { 0 } },
741 static BOOL WINAPI
CRYPT_FormatKeyUsage(DWORD dwCertEncodingType
,
742 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
743 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
747 CRYPT_BIT_BLOB
*bits
;
752 SetLastError(E_INVALIDARG
);
755 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_KEY_USAGE
,
756 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bits
, &size
)))
758 WCHAR infoNotAvailable
[MAX_STRING_RESOURCE_LEN
];
759 DWORD bytesNeeded
= sizeof(WCHAR
);
761 LoadStringW(hInstance
, IDS_INFO_NOT_AVAILABLE
, infoNotAvailable
,
762 sizeof(infoNotAvailable
) / sizeof(infoNotAvailable
[0]));
763 if (!bits
->cbData
|| bits
->cbData
> 2)
765 bytesNeeded
+= strlenW(infoNotAvailable
) * sizeof(WCHAR
);
767 *pcbFormat
= bytesNeeded
;
768 else if (*pcbFormat
< bytesNeeded
)
770 *pcbFormat
= bytesNeeded
;
771 SetLastError(ERROR_MORE_DATA
);
776 LPWSTR str
= pbFormat
;
778 *pcbFormat
= bytesNeeded
;
779 strcpyW(str
, infoNotAvailable
);
784 static BOOL stringsLoaded
= FALSE
;
792 i
< sizeof(keyUsageByte0Map
) / sizeof(keyUsageByte0Map
[0]);
794 LoadStringW(hInstance
, keyUsageByte0Map
[i
].id
,
795 keyUsageByte0Map
[i
].str
, MAX_STRING_RESOURCE_LEN
);
797 i
< sizeof(keyUsageByte1Map
) / sizeof(keyUsageByte1Map
[0]);
799 LoadStringW(hInstance
, keyUsageByte1Map
[i
].id
,
800 keyUsageByte1Map
[i
].str
, MAX_STRING_RESOURCE_LEN
);
801 stringsLoaded
= TRUE
;
803 CRYPT_FormatBits(bits
->pbData
[0], keyUsageByte0Map
,
804 sizeof(keyUsageByte0Map
) / sizeof(keyUsageByte0Map
[0]),
805 NULL
, &bitStringLen
, &first
);
806 bytesNeeded
+= bitStringLen
;
807 if (bits
->cbData
== 2)
809 CRYPT_FormatBits(bits
->pbData
[1], keyUsageByte1Map
,
810 sizeof(keyUsageByte1Map
) / sizeof(keyUsageByte1Map
[0]),
811 NULL
, &bitStringLen
, &first
);
812 bytesNeeded
+= bitStringLen
;
814 bytesNeeded
+= 3 * sizeof(WCHAR
); /* " (" + ")" */
815 CRYPT_FormatHexString(0, 0, 0, NULL
, NULL
, bits
->pbData
,
816 bits
->cbData
, NULL
, &size
);
819 *pcbFormat
= bytesNeeded
;
820 else if (*pcbFormat
< bytesNeeded
)
822 *pcbFormat
= bytesNeeded
;
823 SetLastError(ERROR_MORE_DATA
);
828 LPWSTR str
= pbFormat
;
830 bitStringLen
= bytesNeeded
;
832 CRYPT_FormatBits(bits
->pbData
[0], keyUsageByte0Map
,
833 sizeof(keyUsageByte0Map
) / sizeof(keyUsageByte0Map
[0]),
834 str
, &bitStringLen
, &first
);
835 str
+= bitStringLen
/ sizeof(WCHAR
) - 1;
836 if (bits
->cbData
== 2)
838 bitStringLen
= bytesNeeded
;
839 CRYPT_FormatBits(bits
->pbData
[1], keyUsageByte1Map
,
840 sizeof(keyUsageByte1Map
) / sizeof(keyUsageByte1Map
[0]),
841 str
, &bitStringLen
, &first
);
842 str
+= bitStringLen
/ sizeof(WCHAR
) - 1;
846 CRYPT_FormatHexString(0, 0, 0, NULL
, NULL
, bits
->pbData
,
847 bits
->cbData
, str
, &size
);
848 str
+= size
/ sizeof(WCHAR
) - 1;
858 static const WCHAR crlf
[] = { '\r','\n',0 };
860 static WCHAR subjectTypeHeader
[MAX_STRING_RESOURCE_LEN
];
861 static WCHAR subjectTypeCA
[MAX_STRING_RESOURCE_LEN
];
862 static WCHAR subjectTypeEndCert
[MAX_STRING_RESOURCE_LEN
];
863 static WCHAR pathLengthHeader
[MAX_STRING_RESOURCE_LEN
];
865 static BOOL WINAPI
CRYPT_FormatBasicConstraints2(DWORD dwCertEncodingType
,
866 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
867 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
871 CERT_BASIC_CONSTRAINTS2_INFO
*info
;
876 SetLastError(E_INVALIDARG
);
879 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_BASIC_CONSTRAINTS2
,
880 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &info
, &size
)))
882 static const WCHAR pathFmt
[] = { '%','d',0 };
883 static BOOL stringsLoaded
= FALSE
;
884 DWORD bytesNeeded
= sizeof(WCHAR
); /* space for the NULL terminator */
885 WCHAR pathLength
[MAX_STRING_RESOURCE_LEN
];
886 LPCWSTR sep
, subjectType
;
889 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
892 sepLen
= strlenW(crlf
) * sizeof(WCHAR
);
897 sepLen
= strlenW(commaSpace
) * sizeof(WCHAR
);
902 LoadStringW(hInstance
, IDS_SUBJECT_TYPE
, subjectTypeHeader
,
903 sizeof(subjectTypeHeader
) / sizeof(subjectTypeHeader
[0]));
904 LoadStringW(hInstance
, IDS_SUBJECT_TYPE_CA
, subjectTypeCA
,
905 sizeof(subjectTypeCA
) / sizeof(subjectTypeCA
[0]));
906 LoadStringW(hInstance
, IDS_SUBJECT_TYPE_END_CERT
,
908 sizeof(subjectTypeEndCert
) / sizeof(subjectTypeEndCert
[0]));
909 LoadStringW(hInstance
, IDS_PATH_LENGTH
, pathLengthHeader
,
910 sizeof(pathLengthHeader
) / sizeof(pathLengthHeader
[0]));
911 stringsLoaded
= TRUE
;
913 bytesNeeded
+= strlenW(subjectTypeHeader
) * sizeof(WCHAR
);
915 subjectType
= subjectTypeCA
;
917 subjectType
= subjectTypeEndCert
;
918 bytesNeeded
+= strlenW(subjectType
) * sizeof(WCHAR
);
919 bytesNeeded
+= sepLen
;
920 bytesNeeded
+= strlenW(pathLengthHeader
) * sizeof(WCHAR
);
921 if (info
->fPathLenConstraint
)
922 sprintfW(pathLength
, pathFmt
, info
->dwPathLenConstraint
);
924 LoadStringW(hInstance
, IDS_PATH_LENGTH_NONE
, pathLength
,
925 sizeof(pathLength
) / sizeof(pathLength
[0]));
926 bytesNeeded
+= strlenW(pathLength
) * sizeof(WCHAR
);
928 *pcbFormat
= bytesNeeded
;
929 else if (*pcbFormat
< bytesNeeded
)
931 *pcbFormat
= bytesNeeded
;
932 SetLastError(ERROR_MORE_DATA
);
937 LPWSTR str
= pbFormat
;
939 *pcbFormat
= bytesNeeded
;
940 strcpyW(str
, subjectTypeHeader
);
941 str
+= strlenW(subjectTypeHeader
);
942 strcpyW(str
, subjectType
);
943 str
+= strlenW(subjectType
);
945 str
+= sepLen
/ sizeof(WCHAR
);
946 strcpyW(str
, pathLengthHeader
);
947 str
+= strlenW(pathLengthHeader
);
948 strcpyW(str
, pathLength
);
949 str
+= strlenW(pathLength
);
956 static BOOL
CRYPT_FormatHexStringWithPrefix(CRYPT_DATA_BLOB
*blob
, int id
,
957 LPWSTR str
, DWORD
*pcbStr
)
959 WCHAR buf
[MAX_STRING_RESOURCE_LEN
];
963 LoadStringW(hInstance
, id
, buf
, sizeof(buf
) / sizeof(buf
[0]));
964 CRYPT_FormatHexString(X509_ASN_ENCODING
, 0, 0, NULL
, NULL
,
965 blob
->pbData
, blob
->cbData
, NULL
, &bytesNeeded
);
966 bytesNeeded
+= strlenW(buf
) * sizeof(WCHAR
);
969 *pcbStr
= bytesNeeded
;
972 else if (*pcbStr
< bytesNeeded
)
974 *pcbStr
= bytesNeeded
;
975 SetLastError(ERROR_MORE_DATA
);
980 *pcbStr
= bytesNeeded
;
983 bytesNeeded
-= strlenW(str
) * sizeof(WCHAR
);
984 ret
= CRYPT_FormatHexString(X509_ASN_ENCODING
, 0, 0, NULL
, NULL
,
985 blob
->pbData
, blob
->cbData
, str
, &bytesNeeded
);
990 static BOOL
CRYPT_FormatKeyId(CRYPT_DATA_BLOB
*keyId
, LPWSTR str
,
993 return CRYPT_FormatHexStringWithPrefix(keyId
, IDS_KEY_ID
, str
, pcbStr
);
996 static BOOL
CRYPT_FormatCertSerialNumber(CRYPT_DATA_BLOB
*serialNum
, LPWSTR str
,
999 return CRYPT_FormatHexStringWithPrefix(serialNum
, IDS_CERT_SERIAL_NUMBER
,
1003 static const WCHAR indent
[] = { ' ',' ',' ',' ',' ',0 };
1004 static const WCHAR colonCrlf
[] = { ':','\r','\n',0 };
1006 static BOOL
CRYPT_FormatAltNameEntry(DWORD dwFormatStrType
, DWORD indentLevel
,
1007 CERT_ALT_NAME_ENTRY
*entry
, LPWSTR str
, DWORD
*pcbStr
)
1010 WCHAR buf
[MAX_STRING_RESOURCE_LEN
];
1011 WCHAR mask
[MAX_STRING_RESOURCE_LEN
];
1012 WCHAR ipAddrBuf
[32];
1014 DWORD bytesNeeded
= sizeof(WCHAR
);
1015 DWORD strType
= CERT_X500_NAME_STR
| CERT_NAME_STR_REVERSE_FLAG
;
1017 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1018 bytesNeeded
+= indentLevel
* strlenW(indent
) * sizeof(WCHAR
);
1019 switch (entry
->dwAltNameChoice
)
1021 case CERT_ALT_NAME_RFC822_NAME
:
1022 LoadStringW(hInstance
, IDS_ALT_NAME_RFC822_NAME
, buf
,
1023 sizeof(buf
) / sizeof(buf
[0]));
1024 bytesNeeded
+= strlenW(entry
->u
.pwszRfc822Name
) * sizeof(WCHAR
);
1027 case CERT_ALT_NAME_DNS_NAME
:
1028 LoadStringW(hInstance
, IDS_ALT_NAME_DNS_NAME
, buf
,
1029 sizeof(buf
) / sizeof(buf
[0]));
1030 bytesNeeded
+= strlenW(entry
->u
.pwszDNSName
) * sizeof(WCHAR
);
1033 case CERT_ALT_NAME_DIRECTORY_NAME
:
1035 DWORD directoryNameLen
;
1037 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1038 strType
|= CERT_NAME_STR_CRLF_FLAG
;
1039 directoryNameLen
= cert_name_to_str_with_indent(X509_ASN_ENCODING
,
1040 indentLevel
+ 1, &entry
->u
.DirectoryName
, strType
, NULL
, 0);
1041 LoadStringW(hInstance
, IDS_ALT_NAME_DIRECTORY_NAME
, buf
,
1042 sizeof(buf
) / sizeof(buf
[0]));
1043 bytesNeeded
+= (directoryNameLen
- 1) * sizeof(WCHAR
);
1044 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1045 bytesNeeded
+= strlenW(colonCrlf
) * sizeof(WCHAR
);
1047 bytesNeeded
+= sizeof(WCHAR
); /* '=' */
1051 case CERT_ALT_NAME_URL
:
1052 LoadStringW(hInstance
, IDS_ALT_NAME_URL
, buf
,
1053 sizeof(buf
) / sizeof(buf
[0]));
1054 bytesNeeded
+= strlenW(entry
->u
.pwszURL
) * sizeof(WCHAR
);
1057 case CERT_ALT_NAME_IP_ADDRESS
:
1059 static const WCHAR ipAddrWithMaskFmt
[] = { '%','d','.','%','d','.',
1060 '%','d','.','%','d','/','%','d','.','%','d','.','%','d','.','%','d',0
1062 static const WCHAR ipAddrFmt
[] = { '%','d','.','%','d','.','%','d',
1065 LoadStringW(hInstance
, IDS_ALT_NAME_IP_ADDRESS
, buf
,
1066 sizeof(buf
) / sizeof(buf
[0]));
1067 if (entry
->u
.IPAddress
.cbData
== 8)
1069 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1071 LoadStringW(hInstance
, IDS_ALT_NAME_MASK
, mask
,
1072 sizeof(mask
) / sizeof(mask
[0]));
1073 bytesNeeded
+= strlenW(mask
) * sizeof(WCHAR
);
1074 sprintfW(ipAddrBuf
, ipAddrFmt
,
1075 entry
->u
.IPAddress
.pbData
[0],
1076 entry
->u
.IPAddress
.pbData
[1],
1077 entry
->u
.IPAddress
.pbData
[2],
1078 entry
->u
.IPAddress
.pbData
[3]);
1079 bytesNeeded
+= strlenW(ipAddrBuf
) * sizeof(WCHAR
);
1080 /* indent again, for the mask line */
1081 bytesNeeded
+= indentLevel
* strlenW(indent
) * sizeof(WCHAR
);
1082 sprintfW(maskBuf
, ipAddrFmt
,
1083 entry
->u
.IPAddress
.pbData
[4],
1084 entry
->u
.IPAddress
.pbData
[5],
1085 entry
->u
.IPAddress
.pbData
[6],
1086 entry
->u
.IPAddress
.pbData
[7]);
1087 bytesNeeded
+= strlenW(maskBuf
) * sizeof(WCHAR
);
1088 bytesNeeded
+= strlenW(crlf
) * sizeof(WCHAR
);
1092 sprintfW(ipAddrBuf
, ipAddrWithMaskFmt
,
1093 entry
->u
.IPAddress
.pbData
[0],
1094 entry
->u
.IPAddress
.pbData
[1],
1095 entry
->u
.IPAddress
.pbData
[2],
1096 entry
->u
.IPAddress
.pbData
[3],
1097 entry
->u
.IPAddress
.pbData
[4],
1098 entry
->u
.IPAddress
.pbData
[5],
1099 entry
->u
.IPAddress
.pbData
[6],
1100 entry
->u
.IPAddress
.pbData
[7]);
1101 bytesNeeded
+= (strlenW(ipAddrBuf
) + 1) * sizeof(WCHAR
);
1107 FIXME("unknown IP address format (%d bytes)\n",
1108 entry
->u
.IPAddress
.cbData
);
1114 FIXME("unimplemented for %d\n", entry
->dwAltNameChoice
);
1119 bytesNeeded
+= strlenW(buf
) * sizeof(WCHAR
);
1121 *pcbStr
= bytesNeeded
;
1122 else if (*pcbStr
< bytesNeeded
)
1124 *pcbStr
= bytesNeeded
;
1125 SetLastError(ERROR_MORE_DATA
);
1132 *pcbStr
= bytesNeeded
;
1133 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1135 for (i
= 0; i
< indentLevel
; i
++)
1137 strcpyW(str
, indent
);
1138 str
+= strlenW(indent
);
1142 str
+= strlenW(str
);
1143 switch (entry
->dwAltNameChoice
)
1145 case CERT_ALT_NAME_RFC822_NAME
:
1146 case CERT_ALT_NAME_DNS_NAME
:
1147 case CERT_ALT_NAME_URL
:
1148 strcpyW(str
, entry
->u
.pwszURL
);
1150 case CERT_ALT_NAME_DIRECTORY_NAME
:
1151 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1153 strcpyW(str
, colonCrlf
);
1154 str
+= strlenW(colonCrlf
);
1158 cert_name_to_str_with_indent(X509_ASN_ENCODING
,
1159 indentLevel
+ 1, &entry
->u
.DirectoryName
, strType
, str
,
1160 bytesNeeded
/ sizeof(WCHAR
));
1162 case CERT_ALT_NAME_IP_ADDRESS
:
1163 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1165 strcpyW(str
, ipAddrBuf
);
1166 str
+= strlenW(ipAddrBuf
);
1168 str
+= strlenW(crlf
);
1169 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1171 for (i
= 0; i
< indentLevel
; i
++)
1173 strcpyW(str
, indent
);
1174 str
+= strlenW(indent
);
1178 str
+= strlenW(mask
);
1179 strcpyW(str
, maskBuf
);
1182 strcpyW(str
, ipAddrBuf
);
1190 static BOOL
CRYPT_FormatAltNameInfo(DWORD dwFormatStrType
, DWORD indentLevel
,
1191 CERT_ALT_NAME_INFO
*name
, LPWSTR str
, DWORD
*pcbStr
)
1193 DWORD i
, size
, bytesNeeded
= 0;
1198 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1201 sepLen
= strlenW(crlf
) * sizeof(WCHAR
);
1206 sepLen
= strlenW(commaSpace
) * sizeof(WCHAR
);
1209 for (i
= 0; ret
&& i
< name
->cAltEntry
; i
++)
1211 ret
= CRYPT_FormatAltNameEntry(dwFormatStrType
, indentLevel
,
1212 &name
->rgAltEntry
[i
], NULL
, &size
);
1215 bytesNeeded
+= size
- sizeof(WCHAR
);
1216 if (i
< name
->cAltEntry
- 1)
1217 bytesNeeded
+= sepLen
;
1222 bytesNeeded
+= sizeof(WCHAR
);
1224 *pcbStr
= bytesNeeded
;
1225 else if (*pcbStr
< bytesNeeded
)
1227 *pcbStr
= bytesNeeded
;
1228 SetLastError(ERROR_MORE_DATA
);
1233 *pcbStr
= bytesNeeded
;
1234 for (i
= 0; ret
&& i
< name
->cAltEntry
; i
++)
1236 ret
= CRYPT_FormatAltNameEntry(dwFormatStrType
, indentLevel
,
1237 &name
->rgAltEntry
[i
], str
, &size
);
1240 str
+= size
/ sizeof(WCHAR
) - 1;
1241 if (i
< name
->cAltEntry
- 1)
1244 str
+= sepLen
/ sizeof(WCHAR
);
1253 static const WCHAR colonSep
[] = { ':',' ',0 };
1255 static BOOL WINAPI
CRYPT_FormatAltName(DWORD dwCertEncodingType
,
1256 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
1257 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
1261 CERT_ALT_NAME_INFO
*info
;
1264 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_ALTERNATE_NAME
,
1265 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &info
, &size
)))
1267 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 0, info
, pbFormat
, pcbFormat
);
1273 static BOOL
CRYPT_FormatCertIssuer(DWORD dwFormatStrType
,
1274 CERT_ALT_NAME_INFO
*issuer
, LPWSTR str
, DWORD
*pcbStr
)
1276 WCHAR buf
[MAX_STRING_RESOURCE_LEN
];
1277 DWORD bytesNeeded
, sepLen
;
1281 LoadStringW(hInstance
, IDS_CERT_ISSUER
, buf
, sizeof(buf
) / sizeof(buf
[0]));
1282 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 1, issuer
, NULL
,
1284 bytesNeeded
+= strlenW(buf
) * sizeof(WCHAR
);
1285 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1288 sepLen
= strlenW(colonCrlf
) * sizeof(WCHAR
);
1293 sepLen
= strlenW(colonSep
) * sizeof(WCHAR
);
1295 bytesNeeded
+= sepLen
;
1299 *pcbStr
= bytesNeeded
;
1300 else if (*pcbStr
< bytesNeeded
)
1302 *pcbStr
= bytesNeeded
;
1303 SetLastError(ERROR_MORE_DATA
);
1308 *pcbStr
= bytesNeeded
;
1310 bytesNeeded
-= strlenW(str
) * sizeof(WCHAR
);
1311 str
+= strlenW(str
);
1313 str
+= sepLen
/ sizeof(WCHAR
);
1314 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 1, issuer
, str
,
1321 static BOOL WINAPI
CRYPT_FormatAuthorityKeyId2(DWORD dwCertEncodingType
,
1322 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
1323 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
1326 CERT_AUTHORITY_KEY_ID2_INFO
*info
;
1332 SetLastError(E_INVALIDARG
);
1335 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_AUTHORITY_KEY_ID2
,
1336 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &info
, &size
)))
1338 DWORD bytesNeeded
= sizeof(WCHAR
); /* space for the NULL terminator */
1341 BOOL needSeparator
= FALSE
;
1343 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1346 sepLen
= strlenW(crlf
) * sizeof(WCHAR
);
1351 sepLen
= strlenW(commaSpace
) * sizeof(WCHAR
);
1354 if (info
->KeyId
.cbData
)
1356 needSeparator
= TRUE
;
1357 ret
= CRYPT_FormatKeyId(&info
->KeyId
, NULL
, &size
);
1360 /* don't include NULL-terminator more than once */
1361 bytesNeeded
+= size
- sizeof(WCHAR
);
1364 if (info
->AuthorityCertIssuer
.cAltEntry
)
1367 bytesNeeded
+= sepLen
;
1368 needSeparator
= TRUE
;
1369 ret
= CRYPT_FormatCertIssuer(dwFormatStrType
,
1370 &info
->AuthorityCertIssuer
, NULL
, &size
);
1373 /* don't include NULL-terminator more than once */
1374 bytesNeeded
+= size
- sizeof(WCHAR
);
1377 if (info
->AuthorityCertSerialNumber
.cbData
)
1380 bytesNeeded
+= sepLen
;
1381 ret
= CRYPT_FormatCertSerialNumber(
1382 &info
->AuthorityCertSerialNumber
, NULL
, &size
);
1385 /* don't include NULL-terminator more than once */
1386 bytesNeeded
+= size
- sizeof(WCHAR
);
1392 *pcbFormat
= bytesNeeded
;
1393 else if (*pcbFormat
< bytesNeeded
)
1395 *pcbFormat
= bytesNeeded
;
1396 SetLastError(ERROR_MORE_DATA
);
1401 LPWSTR str
= pbFormat
;
1403 *pcbFormat
= bytesNeeded
;
1404 needSeparator
= FALSE
;
1405 if (info
->KeyId
.cbData
)
1407 needSeparator
= TRUE
;
1408 /* Overestimate size available, it's already been checked
1412 ret
= CRYPT_FormatKeyId(&info
->KeyId
, str
, &size
);
1414 str
+= size
/ sizeof(WCHAR
) - 1;
1416 if (info
->AuthorityCertIssuer
.cAltEntry
)
1421 str
+= sepLen
/ sizeof(WCHAR
);
1423 needSeparator
= TRUE
;
1424 /* Overestimate size available, it's already been checked
1428 ret
= CRYPT_FormatCertIssuer(dwFormatStrType
,
1429 &info
->AuthorityCertIssuer
, str
, &size
);
1431 str
+= size
/ sizeof(WCHAR
) - 1;
1433 if (info
->AuthorityCertSerialNumber
.cbData
)
1438 str
+= sepLen
/ sizeof(WCHAR
);
1440 /* Overestimate size available, it's already been checked
1444 ret
= CRYPT_FormatCertSerialNumber(
1445 &info
->AuthorityCertSerialNumber
, str
, &size
);
1454 static WCHAR aia
[MAX_STRING_RESOURCE_LEN
];
1455 static WCHAR accessMethod
[MAX_STRING_RESOURCE_LEN
];
1456 static WCHAR ocsp
[MAX_STRING_RESOURCE_LEN
];
1457 static WCHAR caIssuers
[MAX_STRING_RESOURCE_LEN
];
1458 static WCHAR unknown
[MAX_STRING_RESOURCE_LEN
];
1459 static WCHAR accessLocation
[MAX_STRING_RESOURCE_LEN
];
1461 static BOOL WINAPI
CRYPT_FormatAuthorityInfoAccess(DWORD dwCertEncodingType
,
1462 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
1463 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
1466 CERT_AUTHORITY_INFO_ACCESS
*info
;
1472 SetLastError(E_INVALIDARG
);
1475 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
,
1476 X509_AUTHORITY_INFO_ACCESS
, pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
,
1477 NULL
, &info
, &size
)))
1479 DWORD bytesNeeded
= sizeof(WCHAR
);
1481 if (!info
->cAccDescr
)
1483 WCHAR infoNotAvailable
[MAX_STRING_RESOURCE_LEN
];
1485 LoadStringW(hInstance
, IDS_INFO_NOT_AVAILABLE
, infoNotAvailable
,
1486 sizeof(infoNotAvailable
) / sizeof(infoNotAvailable
[0]));
1487 bytesNeeded
+= strlenW(infoNotAvailable
) * sizeof(WCHAR
);
1489 *pcbFormat
= bytesNeeded
;
1490 else if (*pcbFormat
< bytesNeeded
)
1492 *pcbFormat
= bytesNeeded
;
1493 SetLastError(ERROR_MORE_DATA
);
1498 *pcbFormat
= bytesNeeded
;
1499 strcpyW((LPWSTR
)pbFormat
, infoNotAvailable
);
1504 static const WCHAR numFmt
[] = { '%','d',0 };
1505 static const WCHAR equal
[] = { '=',0 };
1506 static BOOL stringsLoaded
= FALSE
;
1508 LPCWSTR headingSep
, accessMethodSep
, locationSep
;
1509 WCHAR accessDescrNum
[11];
1513 LoadStringW(hInstance
, IDS_AIA
, aia
,
1514 sizeof(aia
) / sizeof(aia
[0]));
1515 LoadStringW(hInstance
, IDS_ACCESS_METHOD
, accessMethod
,
1516 sizeof(accessMethod
) / sizeof(accessMethod
[0]));
1517 LoadStringW(hInstance
, IDS_ACCESS_METHOD_OCSP
, ocsp
,
1518 sizeof(ocsp
) / sizeof(ocsp
[0]));
1519 LoadStringW(hInstance
, IDS_ACCESS_METHOD_CA_ISSUERS
, caIssuers
,
1520 sizeof(caIssuers
) / sizeof(caIssuers
[0]));
1521 LoadStringW(hInstance
, IDS_ACCESS_METHOD_UNKNOWN
, unknown
,
1522 sizeof(unknown
) / sizeof(unknown
[0]));
1523 LoadStringW(hInstance
, IDS_ACCESS_LOCATION
, accessLocation
,
1524 sizeof(accessLocation
) / sizeof(accessLocation
[0]));
1525 stringsLoaded
= TRUE
;
1527 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1530 accessMethodSep
= crlf
;
1531 locationSep
= colonCrlf
;
1535 headingSep
= colonSep
;
1536 accessMethodSep
= commaSpace
;
1537 locationSep
= equal
;
1540 for (i
= 0; ret
&& i
< info
->cAccDescr
; i
++)
1543 bytesNeeded
+= sizeof(WCHAR
); /* left bracket */
1544 sprintfW(accessDescrNum
, numFmt
, i
+ 1);
1545 bytesNeeded
+= strlenW(accessDescrNum
) * sizeof(WCHAR
);
1546 bytesNeeded
+= sizeof(WCHAR
); /* right bracket */
1547 bytesNeeded
+= strlenW(aia
) * sizeof(WCHAR
);
1548 bytesNeeded
+= strlenW(headingSep
) * sizeof(WCHAR
);
1550 bytesNeeded
+= strlenW(accessMethod
) * sizeof(WCHAR
);
1551 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1552 bytesNeeded
+= strlenW(indent
) * sizeof(WCHAR
);
1553 if (!strcmp(info
->rgAccDescr
[i
].pszAccessMethod
,
1555 bytesNeeded
+= strlenW(ocsp
) * sizeof(WCHAR
);
1556 else if (!strcmp(info
->rgAccDescr
[i
].pszAccessMethod
,
1557 szOID_PKIX_CA_ISSUERS
))
1558 bytesNeeded
+= strlenW(caIssuers
) * sizeof(caIssuers
);
1560 bytesNeeded
+= strlenW(unknown
) * sizeof(WCHAR
);
1561 bytesNeeded
+= sizeof(WCHAR
); /* space */
1562 bytesNeeded
+= sizeof(WCHAR
); /* left paren */
1563 bytesNeeded
+= strlen(info
->rgAccDescr
[i
].pszAccessMethod
)
1565 bytesNeeded
+= sizeof(WCHAR
); /* right paren */
1566 /* Delimiter between access method and location */
1567 bytesNeeded
+= strlenW(accessMethodSep
) * sizeof(WCHAR
);
1568 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1569 bytesNeeded
+= strlenW(indent
) * sizeof(WCHAR
);
1570 bytesNeeded
+= strlenW(accessLocation
) * sizeof(WCHAR
);
1571 bytesNeeded
+= strlenW(locationSep
) * sizeof(WCHAR
);
1572 ret
= CRYPT_FormatAltNameEntry(dwFormatStrType
, 2,
1573 &info
->rgAccDescr
[i
].AccessLocation
, NULL
, &size
);
1575 bytesNeeded
+= size
- sizeof(WCHAR
);
1576 /* Need extra delimiter between access method entries */
1577 if (i
< info
->cAccDescr
- 1)
1578 bytesNeeded
+= strlenW(accessMethodSep
) * sizeof(WCHAR
);
1583 *pcbFormat
= bytesNeeded
;
1584 else if (*pcbFormat
< bytesNeeded
)
1586 *pcbFormat
= bytesNeeded
;
1587 SetLastError(ERROR_MORE_DATA
);
1592 LPWSTR str
= pbFormat
;
1593 DWORD altNameEntrySize
;
1595 *pcbFormat
= bytesNeeded
;
1596 for (i
= 0; ret
&& i
< info
->cAccDescr
; i
++)
1601 sprintfW(accessDescrNum
, numFmt
, i
+ 1);
1602 strcpyW(str
, accessDescrNum
);
1603 str
+= strlenW(accessDescrNum
);
1606 str
+= strlenW(aia
);
1607 strcpyW(str
, headingSep
);
1608 str
+= strlenW(headingSep
);
1609 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1611 strcpyW(str
, indent
);
1612 str
+= strlenW(indent
);
1614 strcpyW(str
, accessMethod
);
1615 str
+= strlenW(accessMethod
);
1616 if (!strcmp(info
->rgAccDescr
[i
].pszAccessMethod
,
1620 str
+= strlenW(ocsp
);
1622 else if (!strcmp(info
->rgAccDescr
[i
].pszAccessMethod
,
1623 szOID_PKIX_CA_ISSUERS
))
1625 strcpyW(str
, caIssuers
);
1626 str
+= strlenW(caIssuers
);
1630 strcpyW(str
, unknown
);
1631 str
+= strlenW(unknown
);
1635 for (oidPtr
= info
->rgAccDescr
[i
].pszAccessMethod
;
1636 *oidPtr
; oidPtr
++, str
++)
1639 strcpyW(str
, accessMethodSep
);
1640 str
+= strlenW(accessMethodSep
);
1641 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1643 strcpyW(str
, indent
);
1644 str
+= strlenW(indent
);
1646 strcpyW(str
, accessLocation
);
1647 str
+= strlenW(accessLocation
);
1648 strcpyW(str
, locationSep
);
1649 str
+= strlenW(locationSep
);
1650 /* This overestimates the size available, but that
1651 * won't matter since we checked earlier whether enough
1652 * space for the entire string was available.
1654 altNameEntrySize
= bytesNeeded
;
1655 ret
= CRYPT_FormatAltNameEntry(dwFormatStrType
, 2,
1656 &info
->rgAccDescr
[i
].AccessLocation
, str
,
1659 str
+= altNameEntrySize
/ sizeof(WCHAR
) - 1;
1660 if (i
< info
->cAccDescr
- 1)
1662 strcpyW(str
, accessMethodSep
);
1663 str
+= strlenW(accessMethodSep
);
1674 static WCHAR keyCompromise
[MAX_STRING_RESOURCE_LEN
];
1675 static WCHAR caCompromise
[MAX_STRING_RESOURCE_LEN
];
1676 static WCHAR affiliationChanged
[MAX_STRING_RESOURCE_LEN
];
1677 static WCHAR superseded
[MAX_STRING_RESOURCE_LEN
];
1678 static WCHAR operationCeased
[MAX_STRING_RESOURCE_LEN
];
1679 static WCHAR certificateHold
[MAX_STRING_RESOURCE_LEN
];
1681 struct reason_map_entry
1687 static struct reason_map_entry reason_map
[] = {
1688 { CRL_REASON_KEY_COMPROMISE_FLAG
, keyCompromise
, IDS_REASON_KEY_COMPROMISE
},
1689 { CRL_REASON_CA_COMPROMISE_FLAG
, caCompromise
, IDS_REASON_CA_COMPROMISE
},
1690 { CRL_REASON_AFFILIATION_CHANGED_FLAG
, affiliationChanged
,
1691 IDS_REASON_AFFILIATION_CHANGED
},
1692 { CRL_REASON_SUPERSEDED_FLAG
, superseded
, IDS_REASON_SUPERSEDED
},
1693 { CRL_REASON_CESSATION_OF_OPERATION_FLAG
, operationCeased
,
1694 IDS_REASON_CESSATION_OF_OPERATION
},
1695 { CRL_REASON_CERTIFICATE_HOLD_FLAG
, certificateHold
,
1696 IDS_REASON_CERTIFICATE_HOLD
},
1699 static BOOL
CRYPT_FormatReason(DWORD dwFormatStrType
,
1700 const CRYPT_BIT_BLOB
*reasonFlags
, LPWSTR str
, DWORD
*pcbStr
)
1702 static const WCHAR sep
[] = { ',',' ',0 };
1703 static const WCHAR bitsFmt
[] = { ' ','(','%','0','2','x',')',0 };
1704 static BOOL stringsLoaded
= FALSE
;
1705 int i
, numReasons
= 0;
1707 DWORD bytesNeeded
= sizeof(WCHAR
);
1712 for (i
= 0; i
< sizeof(reason_map
) / sizeof(reason_map
[0]); i
++)
1713 LoadStringW(hInstance
, reason_map
[i
].id
, reason_map
[i
].reason
,
1714 MAX_STRING_RESOURCE_LEN
);
1715 stringsLoaded
= TRUE
;
1717 /* No need to check reasonFlags->cbData, we already know it's positive.
1718 * Ignore any other bytes, as they're for undefined bits.
1720 for (i
= 0; i
< sizeof(reason_map
) / sizeof(reason_map
[0]); i
++)
1722 if (reasonFlags
->pbData
[0] & reason_map
[i
].reasonBit
)
1724 bytesNeeded
+= strlenW(reason_map
[i
].reason
) * sizeof(WCHAR
);
1726 bytesNeeded
+= strlenW(sep
) * sizeof(WCHAR
);
1729 sprintfW(bits
, bitsFmt
, reasonFlags
->pbData
[0]);
1730 bytesNeeded
+= strlenW(bits
);
1732 *pcbStr
= bytesNeeded
;
1733 else if (*pcbStr
< bytesNeeded
)
1735 *pcbStr
= bytesNeeded
;
1736 SetLastError(ERROR_MORE_DATA
);
1741 *pcbStr
= bytesNeeded
;
1742 for (i
= 0; i
< sizeof(reason_map
) / sizeof(reason_map
[0]); i
++)
1744 if (reasonFlags
->pbData
[0] & reason_map
[i
].reasonBit
)
1746 strcpyW(str
, reason_map
[i
].reason
);
1747 str
+= strlenW(reason_map
[i
].reason
);
1748 if (i
< sizeof(reason_map
) / sizeof(reason_map
[0]) - 1 &&
1752 str
+= strlenW(sep
);
1761 static WCHAR crlDistPoint
[MAX_STRING_RESOURCE_LEN
];
1762 static WCHAR distPointName
[MAX_STRING_RESOURCE_LEN
];
1763 static WCHAR fullName
[MAX_STRING_RESOURCE_LEN
];
1764 static WCHAR rdnName
[MAX_STRING_RESOURCE_LEN
];
1765 static WCHAR reason
[MAX_STRING_RESOURCE_LEN
];
1766 static WCHAR issuer
[MAX_STRING_RESOURCE_LEN
];
1768 static BOOL WINAPI
CRYPT_FormatCRLDistPoints(DWORD dwCertEncodingType
,
1769 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
1770 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
1773 CRL_DIST_POINTS_INFO
*info
;
1779 SetLastError(E_INVALIDARG
);
1782 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_CRL_DIST_POINTS
,
1783 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &info
, &size
)))
1785 static const WCHAR numFmt
[] = { '%','d',0 };
1786 static const WCHAR colon
[] = { ':',0 };
1787 static BOOL stringsLoaded
= FALSE
;
1788 DWORD bytesNeeded
= sizeof(WCHAR
); /* space for NULL terminator */
1789 BOOL haveAnEntry
= FALSE
;
1790 LPCWSTR headingSep
, nameSep
;
1791 WCHAR distPointNum
[11];
1796 LoadStringW(hInstance
, IDS_CRL_DIST_POINT
, crlDistPoint
,
1797 sizeof(crlDistPoint
) / sizeof(crlDistPoint
[0]));
1798 LoadStringW(hInstance
, IDS_CRL_DIST_POINT_NAME
, distPointName
,
1799 sizeof(distPointName
) / sizeof(distPointName
[0]));
1800 LoadStringW(hInstance
, IDS_CRL_DIST_POINT_FULL_NAME
, fullName
,
1801 sizeof(fullName
) / sizeof(fullName
[0]));
1802 LoadStringW(hInstance
, IDS_CRL_DIST_POINT_RDN_NAME
, rdnName
,
1803 sizeof(rdnName
) / sizeof(rdnName
[0]));
1804 LoadStringW(hInstance
, IDS_CRL_DIST_POINT_REASON
, reason
,
1805 sizeof(reason
) / sizeof(reason
[0]));
1806 LoadStringW(hInstance
, IDS_CRL_DIST_POINT_ISSUER
, issuer
,
1807 sizeof(issuer
) / sizeof(issuer
[0]));
1808 stringsLoaded
= TRUE
;
1810 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1813 nameSep
= colonCrlf
;
1817 headingSep
= colonSep
;
1821 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
1823 CRL_DIST_POINT
*distPoint
= &info
->rgDistPoint
[i
];
1825 if (distPoint
->DistPointName
.dwDistPointNameChoice
!=
1826 CRL_DIST_POINT_NO_NAME
)
1828 bytesNeeded
+= strlenW(distPointName
) * sizeof(WCHAR
);
1829 bytesNeeded
+= strlenW(nameSep
) * sizeof(WCHAR
);
1830 if (distPoint
->DistPointName
.dwDistPointNameChoice
==
1831 CRL_DIST_POINT_FULL_NAME
)
1832 bytesNeeded
+= strlenW(fullName
) * sizeof(WCHAR
);
1834 bytesNeeded
+= strlenW(rdnName
) * sizeof(WCHAR
);
1835 bytesNeeded
+= strlenW(nameSep
) * sizeof(WCHAR
);
1836 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1837 bytesNeeded
+= 2 * strlenW(indent
) * sizeof(WCHAR
);
1838 /* The indent level (3) is higher than when used as the issuer,
1839 * because the name is subordinate to the name type (full vs.
1842 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 3,
1843 &distPoint
->DistPointName
.u
.FullName
, NULL
, &size
);
1845 bytesNeeded
+= size
- sizeof(WCHAR
);
1848 else if (distPoint
->ReasonFlags
.cbData
)
1850 bytesNeeded
+= strlenW(reason
) * sizeof(WCHAR
);
1851 ret
= CRYPT_FormatReason(dwFormatStrType
,
1852 &distPoint
->ReasonFlags
, NULL
, &size
);
1854 bytesNeeded
+= size
- sizeof(WCHAR
);
1857 else if (distPoint
->CRLIssuer
.cAltEntry
)
1859 bytesNeeded
+= strlenW(issuer
) * sizeof(WCHAR
);
1860 bytesNeeded
+= strlenW(nameSep
) * sizeof(WCHAR
);
1861 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 2,
1862 &distPoint
->CRLIssuer
, NULL
, &size
);
1864 bytesNeeded
+= size
- sizeof(WCHAR
);
1869 bytesNeeded
+= sizeof(WCHAR
); /* left bracket */
1870 sprintfW(distPointNum
, numFmt
, i
+ 1);
1871 bytesNeeded
+= strlenW(distPointNum
) * sizeof(WCHAR
);
1872 bytesNeeded
+= sizeof(WCHAR
); /* right bracket */
1873 bytesNeeded
+= strlenW(crlDistPoint
) * sizeof(WCHAR
);
1874 bytesNeeded
+= strlenW(headingSep
) * sizeof(WCHAR
);
1875 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1876 bytesNeeded
+= strlenW(indent
) * sizeof(WCHAR
);
1881 WCHAR infoNotAvailable
[MAX_STRING_RESOURCE_LEN
];
1883 LoadStringW(hInstance
, IDS_INFO_NOT_AVAILABLE
, infoNotAvailable
,
1884 sizeof(infoNotAvailable
) / sizeof(infoNotAvailable
[0]));
1885 bytesNeeded
+= strlenW(infoNotAvailable
) * sizeof(WCHAR
);
1887 *pcbFormat
= bytesNeeded
;
1888 else if (*pcbFormat
< bytesNeeded
)
1890 *pcbFormat
= bytesNeeded
;
1891 SetLastError(ERROR_MORE_DATA
);
1896 *pcbFormat
= bytesNeeded
;
1897 strcpyW((LPWSTR
)pbFormat
, infoNotAvailable
);
1903 *pcbFormat
= bytesNeeded
;
1904 else if (*pcbFormat
< bytesNeeded
)
1906 *pcbFormat
= bytesNeeded
;
1907 SetLastError(ERROR_MORE_DATA
);
1912 LPWSTR str
= pbFormat
;
1914 *pcbFormat
= bytesNeeded
;
1915 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
1917 CRL_DIST_POINT
*distPoint
= &info
->rgDistPoint
[i
];
1920 sprintfW(distPointNum
, numFmt
, i
+ 1);
1921 strcpyW(str
, distPointNum
);
1922 str
+= strlenW(distPointNum
);
1924 strcpyW(str
, crlDistPoint
);
1925 str
+= strlenW(crlDistPoint
);
1926 strcpyW(str
, headingSep
);
1927 str
+= strlenW(headingSep
);
1928 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1930 strcpyW(str
, indent
);
1931 str
+= strlenW(indent
);
1933 if (distPoint
->DistPointName
.dwDistPointNameChoice
!=
1934 CRL_DIST_POINT_NO_NAME
)
1936 DWORD altNameSize
= bytesNeeded
;
1938 strcpyW(str
, distPointName
);
1939 str
+= strlenW(distPointName
);
1940 strcpyW(str
, nameSep
);
1941 str
+= strlenW(nameSep
);
1942 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1944 strcpyW(str
, indent
);
1945 str
+= strlenW(indent
);
1946 strcpyW(str
, indent
);
1947 str
+= strlenW(indent
);
1949 if (distPoint
->DistPointName
.dwDistPointNameChoice
==
1950 CRL_DIST_POINT_FULL_NAME
)
1952 strcpyW(str
, fullName
);
1953 str
+= strlenW(fullName
);
1957 strcpyW(str
, rdnName
);
1958 str
+= strlenW(rdnName
);
1960 strcpyW(str
, nameSep
);
1961 str
+= strlenW(nameSep
);
1962 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 3,
1963 &distPoint
->DistPointName
.u
.FullName
, str
,
1966 str
+= altNameSize
/ sizeof(WCHAR
) - 1;
1968 else if (distPoint
->ReasonFlags
.cbData
)
1970 DWORD reasonSize
= bytesNeeded
;
1972 strcpyW(str
, reason
);
1973 str
+= strlenW(reason
);
1974 ret
= CRYPT_FormatReason(dwFormatStrType
,
1975 &distPoint
->ReasonFlags
, str
, &reasonSize
);
1977 str
+= reasonSize
/ sizeof(WCHAR
) - 1;
1979 else if (distPoint
->CRLIssuer
.cAltEntry
)
1981 DWORD crlIssuerSize
= bytesNeeded
;
1983 strcpyW(str
, issuer
);
1984 str
+= strlenW(issuer
);
1985 strcpyW(str
, nameSep
);
1986 str
+= strlenW(nameSep
);
1987 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 2,
1988 &distPoint
->CRLIssuer
, str
,
1991 str
+= crlIssuerSize
/ sizeof(WCHAR
) - 1;
2001 static BOOL WINAPI
CRYPT_FormatEnhancedKeyUsage(DWORD dwCertEncodingType
,
2002 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
2003 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
2006 CERT_ENHKEY_USAGE
*usage
;
2012 SetLastError(E_INVALIDARG
);
2015 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_ENHANCED_KEY_USAGE
,
2016 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &usage
, &size
)))
2018 WCHAR unknown
[MAX_STRING_RESOURCE_LEN
];
2020 DWORD bytesNeeded
= sizeof(WCHAR
); /* space for the NULL terminator */
2024 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
2027 sepLen
= strlenW(crlf
) * sizeof(WCHAR
);
2032 sepLen
= strlenW(commaSpace
) * sizeof(WCHAR
);
2035 LoadStringW(hInstance
, IDS_USAGE_UNKNOWN
, unknown
,
2036 sizeof(unknown
) / sizeof(unknown
[0]));
2037 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
2039 PCCRYPT_OID_INFO info
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2040 usage
->rgpszUsageIdentifier
[i
], CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
2043 bytesNeeded
+= strlenW(info
->pwszName
) * sizeof(WCHAR
);
2045 bytesNeeded
+= strlenW(unknown
) * sizeof(WCHAR
);
2046 bytesNeeded
+= sizeof(WCHAR
); /* space */
2047 bytesNeeded
+= sizeof(WCHAR
); /* left paren */
2048 bytesNeeded
+= strlen(usage
->rgpszUsageIdentifier
[i
]) *
2050 bytesNeeded
+= sizeof(WCHAR
); /* right paren */
2051 if (i
< usage
->cUsageIdentifier
- 1)
2052 bytesNeeded
+= sepLen
;
2055 *pcbFormat
= bytesNeeded
;
2056 else if (*pcbFormat
< bytesNeeded
)
2058 *pcbFormat
= bytesNeeded
;
2059 SetLastError(ERROR_MORE_DATA
);
2064 LPWSTR str
= pbFormat
;
2066 *pcbFormat
= bytesNeeded
;
2067 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
2069 PCCRYPT_OID_INFO info
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2070 usage
->rgpszUsageIdentifier
[i
],
2071 CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
2076 strcpyW(str
, info
->pwszName
);
2077 str
+= strlenW(info
->pwszName
);
2081 strcpyW(str
, unknown
);
2082 str
+= strlenW(unknown
);
2086 for (oidPtr
= usage
->rgpszUsageIdentifier
[i
]; *oidPtr
; oidPtr
++)
2090 if (i
< usage
->cUsageIdentifier
- 1)
2093 str
+= sepLen
/ sizeof(WCHAR
);
2102 static struct BitToString netscapeCertTypeMap
[] = {
2103 { NETSCAPE_SSL_CLIENT_AUTH_CERT_TYPE
, IDS_NETSCAPE_SSL_CLIENT
, { 0 } },
2104 { NETSCAPE_SSL_SERVER_AUTH_CERT_TYPE
, IDS_NETSCAPE_SSL_SERVER
, { 0 } },
2105 { NETSCAPE_SMIME_CERT_TYPE
, IDS_NETSCAPE_SMIME
, { 0 } },
2106 { NETSCAPE_SIGN_CERT_TYPE
, IDS_NETSCAPE_SIGN
, { 0 } },
2107 { NETSCAPE_SSL_CA_CERT_TYPE
, IDS_NETSCAPE_SSL_CA
, { 0 } },
2108 { NETSCAPE_SMIME_CA_CERT_TYPE
, IDS_NETSCAPE_SMIME_CA
, { 0 } },
2109 { NETSCAPE_SIGN_CA_CERT_TYPE
, IDS_NETSCAPE_SIGN_CA
, { 0 } },
2112 static BOOL WINAPI
CRYPT_FormatNetscapeCertType(DWORD dwCertEncodingType
,
2113 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
2114 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
2118 CRYPT_BIT_BLOB
*bits
;
2123 SetLastError(E_INVALIDARG
);
2126 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_BITS
,
2127 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bits
, &size
)))
2129 WCHAR infoNotAvailable
[MAX_STRING_RESOURCE_LEN
];
2130 DWORD bytesNeeded
= sizeof(WCHAR
);
2132 LoadStringW(hInstance
, IDS_INFO_NOT_AVAILABLE
, infoNotAvailable
,
2133 sizeof(infoNotAvailable
) / sizeof(infoNotAvailable
[0]));
2134 if (!bits
->cbData
|| bits
->cbData
> 1)
2136 bytesNeeded
+= strlenW(infoNotAvailable
) * sizeof(WCHAR
);
2138 *pcbFormat
= bytesNeeded
;
2139 else if (*pcbFormat
< bytesNeeded
)
2141 *pcbFormat
= bytesNeeded
;
2142 SetLastError(ERROR_MORE_DATA
);
2147 LPWSTR str
= pbFormat
;
2149 *pcbFormat
= bytesNeeded
;
2150 strcpyW(str
, infoNotAvailable
);
2155 static BOOL stringsLoaded
= FALSE
;
2162 for (i
= 0; i
< sizeof(netscapeCertTypeMap
) /
2163 sizeof(netscapeCertTypeMap
[0]); i
++)
2164 LoadStringW(hInstance
, netscapeCertTypeMap
[i
].id
,
2165 netscapeCertTypeMap
[i
].str
, MAX_STRING_RESOURCE_LEN
);
2166 stringsLoaded
= TRUE
;
2168 CRYPT_FormatBits(bits
->pbData
[0], netscapeCertTypeMap
,
2169 sizeof(netscapeCertTypeMap
) / sizeof(netscapeCertTypeMap
[0]),
2170 NULL
, &bitStringLen
, &first
);
2171 bytesNeeded
+= bitStringLen
;
2172 bytesNeeded
+= 3 * sizeof(WCHAR
); /* " (" + ")" */
2173 CRYPT_FormatHexString(0, 0, 0, NULL
, NULL
, bits
->pbData
,
2174 bits
->cbData
, NULL
, &size
);
2175 bytesNeeded
+= size
;
2177 *pcbFormat
= bytesNeeded
;
2178 else if (*pcbFormat
< bytesNeeded
)
2180 *pcbFormat
= bytesNeeded
;
2181 SetLastError(ERROR_MORE_DATA
);
2186 LPWSTR str
= pbFormat
;
2188 bitStringLen
= bytesNeeded
;
2190 CRYPT_FormatBits(bits
->pbData
[0], netscapeCertTypeMap
,
2191 sizeof(netscapeCertTypeMap
) / sizeof(netscapeCertTypeMap
[0]),
2192 str
, &bitStringLen
, &first
);
2193 str
+= bitStringLen
/ sizeof(WCHAR
) - 1;
2196 CRYPT_FormatHexString(0, 0, 0, NULL
, NULL
, bits
->pbData
,
2197 bits
->cbData
, str
, &size
);
2198 str
+= size
/ sizeof(WCHAR
) - 1;
2208 static WCHAR financialCriteria
[MAX_STRING_RESOURCE_LEN
];
2209 static WCHAR available
[MAX_STRING_RESOURCE_LEN
];
2210 static WCHAR notAvailable
[MAX_STRING_RESOURCE_LEN
];
2211 static WCHAR meetsCriteria
[MAX_STRING_RESOURCE_LEN
];
2212 static WCHAR yes
[MAX_STRING_RESOURCE_LEN
];
2213 static WCHAR no
[MAX_STRING_RESOURCE_LEN
];
2215 static BOOL WINAPI
CRYPT_FormatSpcFinancialCriteria(DWORD dwCertEncodingType
,
2216 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
2217 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
2220 SPC_FINANCIAL_CRITERIA criteria
;
2221 DWORD size
= sizeof(criteria
);
2226 SetLastError(E_INVALIDARG
);
2229 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
,
2230 SPC_FINANCIAL_CRITERIA_STRUCT
, pbEncoded
, cbEncoded
, 0, NULL
, &criteria
,
2233 static BOOL stringsLoaded
= FALSE
;
2234 DWORD bytesNeeded
= sizeof(WCHAR
);
2240 LoadStringW(hInstance
, IDS_FINANCIAL_CRITERIA
, financialCriteria
,
2241 sizeof(financialCriteria
) / sizeof(financialCriteria
[0]));
2242 LoadStringW(hInstance
, IDS_FINANCIAL_CRITERIA_AVAILABLE
, available
,
2243 sizeof(available
) / sizeof(available
[0]));
2244 LoadStringW(hInstance
, IDS_FINANCIAL_CRITERIA_NOT_AVAILABLE
,
2245 notAvailable
, sizeof(notAvailable
) / sizeof(notAvailable
[0]));
2246 LoadStringW(hInstance
, IDS_FINANCIAL_CRITERIA_MEETS_CRITERIA
,
2247 meetsCriteria
, sizeof(meetsCriteria
) / sizeof(meetsCriteria
[0]));
2248 LoadStringW(hInstance
, IDS_YES
, yes
, sizeof(yes
) / sizeof(yes
[0]));
2249 LoadStringW(hInstance
, IDS_NO
, no
, sizeof(no
) / sizeof(no
[0]));
2250 stringsLoaded
= TRUE
;
2252 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
2255 sepLen
= strlenW(crlf
) * sizeof(WCHAR
);
2260 sepLen
= strlenW(commaSpace
) * sizeof(WCHAR
);
2262 bytesNeeded
+= strlenW(financialCriteria
) * sizeof(WCHAR
);
2263 if (criteria
.fFinancialInfoAvailable
)
2265 bytesNeeded
+= strlenW(available
) * sizeof(WCHAR
);
2266 bytesNeeded
+= sepLen
;
2267 bytesNeeded
+= strlenW(meetsCriteria
) * sizeof(WCHAR
);
2268 if (criteria
.fMeetsCriteria
)
2269 bytesNeeded
+= strlenW(yes
) * sizeof(WCHAR
);
2271 bytesNeeded
+= strlenW(no
) * sizeof(WCHAR
);
2274 bytesNeeded
+= strlenW(notAvailable
) * sizeof(WCHAR
);
2276 *pcbFormat
= bytesNeeded
;
2277 else if (*pcbFormat
< bytesNeeded
)
2279 *pcbFormat
= bytesNeeded
;
2280 SetLastError(ERROR_MORE_DATA
);
2285 LPWSTR str
= pbFormat
;
2287 *pcbFormat
= bytesNeeded
;
2288 strcpyW(str
, financialCriteria
);
2289 str
+= strlenW(financialCriteria
);
2290 if (criteria
.fFinancialInfoAvailable
)
2292 strcpyW(str
, available
);
2293 str
+= strlenW(available
);
2295 str
+= sepLen
/ sizeof(WCHAR
);
2296 strcpyW(str
, meetsCriteria
);
2297 str
+= strlenW(meetsCriteria
);
2298 if (criteria
.fMeetsCriteria
)
2305 strcpyW(str
, notAvailable
);
2306 str
+= strlenW(notAvailable
);
2313 static BOOL WINAPI
CRYPT_FormatUnicodeString(DWORD dwCertEncodingType
,
2314 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
2315 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
2318 CERT_NAME_VALUE
*value
;
2324 SetLastError(E_INVALIDARG
);
2327 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_UNICODE_ANY_STRING
,
2328 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &value
, &size
)))
2331 *pcbFormat
= value
->Value
.cbData
;
2332 else if (*pcbFormat
< value
->Value
.cbData
)
2334 *pcbFormat
= value
->Value
.cbData
;
2335 SetLastError(ERROR_MORE_DATA
);
2340 LPWSTR str
= pbFormat
;
2342 *pcbFormat
= value
->Value
.cbData
;
2343 strcpyW(str
, (LPWSTR
)value
->Value
.pbData
);
2349 typedef BOOL (WINAPI
*CryptFormatObjectFunc
)(DWORD
, DWORD
, DWORD
, void *,
2350 LPCSTR
, const BYTE
*, DWORD
, void *, DWORD
*);
2352 static CryptFormatObjectFunc
CRYPT_GetBuiltinFormatFunction(DWORD encodingType
,
2353 DWORD formatStrType
, LPCSTR lpszStructType
)
2355 CryptFormatObjectFunc format
= NULL
;
2357 if ((encodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
)
2359 SetLastError(ERROR_FILE_NOT_FOUND
);
2362 if (!HIWORD(lpszStructType
))
2364 switch (LOWORD(lpszStructType
))
2366 case LOWORD(X509_KEY_USAGE
):
2367 format
= CRYPT_FormatKeyUsage
;
2369 case LOWORD(X509_ALTERNATE_NAME
):
2370 format
= CRYPT_FormatAltName
;
2372 case LOWORD(X509_BASIC_CONSTRAINTS2
):
2373 format
= CRYPT_FormatBasicConstraints2
;
2375 case LOWORD(X509_AUTHORITY_KEY_ID2
):
2376 format
= CRYPT_FormatAuthorityKeyId2
;
2378 case LOWORD(X509_AUTHORITY_INFO_ACCESS
):
2379 format
= CRYPT_FormatAuthorityInfoAccess
;
2381 case LOWORD(X509_CRL_DIST_POINTS
):
2382 format
= CRYPT_FormatCRLDistPoints
;
2384 case LOWORD(X509_ENHANCED_KEY_USAGE
):
2385 format
= CRYPT_FormatEnhancedKeyUsage
;
2387 case LOWORD(SPC_FINANCIAL_CRITERIA_STRUCT
):
2388 format
= CRYPT_FormatSpcFinancialCriteria
;
2392 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
2393 format
= CRYPT_FormatAltName
;
2394 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
2395 format
= CRYPT_FormatAltName
;
2396 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
2397 format
= CRYPT_FormatKeyUsage
;
2398 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
2399 format
= CRYPT_FormatAltName
;
2400 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
2401 format
= CRYPT_FormatAltName
;
2402 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
2403 format
= CRYPT_FormatBasicConstraints2
;
2404 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_INFO_ACCESS
))
2405 format
= CRYPT_FormatAuthorityInfoAccess
;
2406 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
2407 format
= CRYPT_FormatAuthorityKeyId2
;
2408 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
2409 format
= CRYPT_FormatCRLDistPoints
;
2410 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
2411 format
= CRYPT_FormatEnhancedKeyUsage
;
2412 else if (!strcmp(lpszStructType
, szOID_NETSCAPE_CERT_TYPE
))
2413 format
= CRYPT_FormatNetscapeCertType
;
2414 else if (!strcmp(lpszStructType
, szOID_NETSCAPE_BASE_URL
) ||
2415 !strcmp(lpszStructType
, szOID_NETSCAPE_REVOCATION_URL
) ||
2416 !strcmp(lpszStructType
, szOID_NETSCAPE_CA_REVOCATION_URL
) ||
2417 !strcmp(lpszStructType
, szOID_NETSCAPE_CERT_RENEWAL_URL
) ||
2418 !strcmp(lpszStructType
, szOID_NETSCAPE_CA_POLICY_URL
) ||
2419 !strcmp(lpszStructType
, szOID_NETSCAPE_SSL_SERVER_NAME
) ||
2420 !strcmp(lpszStructType
, szOID_NETSCAPE_COMMENT
))
2421 format
= CRYPT_FormatUnicodeString
;
2422 else if (!strcmp(lpszStructType
, SPC_FINANCIAL_CRITERIA_OBJID
))
2423 format
= CRYPT_FormatSpcFinancialCriteria
;
2427 BOOL WINAPI
CryptFormatObject(DWORD dwCertEncodingType
, DWORD dwFormatType
,
2428 DWORD dwFormatStrType
, void *pFormatStruct
, LPCSTR lpszStructType
,
2429 const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
, DWORD
*pcbFormat
)
2431 CryptFormatObjectFunc format
= NULL
;
2432 HCRYPTOIDFUNCADDR hFunc
= NULL
;
2435 TRACE("(%08x, %d, %08x, %p, %s, %p, %d, %p, %p)\n", dwCertEncodingType
,
2436 dwFormatType
, dwFormatStrType
, pFormatStruct
, debugstr_a(lpszStructType
),
2437 pbEncoded
, cbEncoded
, pbFormat
, pcbFormat
);
2439 if (!(format
= CRYPT_GetBuiltinFormatFunction(dwCertEncodingType
,
2440 dwFormatStrType
, lpszStructType
)))
2442 static HCRYPTOIDFUNCSET set
= NULL
;
2445 set
= CryptInitOIDFunctionSet(CRYPT_OID_FORMAT_OBJECT_FUNC
, 0);
2446 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
2447 (void **)&format
, &hFunc
);
2449 if (!format
&& (dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) ==
2450 X509_ASN_ENCODING
&& !(dwFormatStrType
& CRYPT_FORMAT_STR_NO_HEX
))
2451 format
= CRYPT_FormatHexString
;
2453 ret
= format(dwCertEncodingType
, dwFormatType
, dwFormatStrType
,
2454 pFormatStruct
, lpszStructType
, pbEncoded
, cbEncoded
, pbFormat
,
2457 CryptFreeOIDFunctionAddress(hFunc
, 0);