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
25 #include "crypt32_private.h"
26 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
30 static BOOL
CRYPT_ReadBlobFromFile(LPCWSTR fileName
, PCERT_BLOB blob
)
35 TRACE("%s\n", debugstr_w(fileName
));
37 file
= CreateFileW(fileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
38 OPEN_EXISTING
, 0, NULL
);
39 if (file
!= INVALID_HANDLE_VALUE
)
42 blob
->cbData
= GetFileSize(file
, NULL
);
45 blob
->pbData
= CryptMemAlloc(blob
->cbData
);
50 ret
= ReadFile(file
, blob
->pbData
, blob
->cbData
, &read
, NULL
);
55 TRACE("returning %d\n", ret
);
59 static BOOL
CRYPT_QueryContextObject(DWORD dwObjectType
, const void *pvObject
,
60 DWORD dwExpectedContentTypeFlags
, DWORD
*pdwMsgAndCertEncodingType
,
61 DWORD
*pdwContentType
, HCERTSTORE
*phCertStore
, const void **ppvContext
)
64 const CERT_BLOB
*blob
;
71 case CERT_QUERY_OBJECT_FILE
:
72 /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so
73 * just read the file directly
75 ret
= CRYPT_ReadBlobFromFile((LPCWSTR
)pvObject
, &fileBlob
);
78 case CERT_QUERY_OBJECT_BLOB
:
79 blob
= (const CERT_BLOB
*)pvObject
;
83 SetLastError(E_INVALIDARG
); /* FIXME: is this the correct error? */
89 store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
90 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
92 if (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CERT
)
94 ret
= pCertInterface
->addEncodedToStore(store
, X509_ASN_ENCODING
,
95 blob
->pbData
, blob
->cbData
, CERT_STORE_ADD_ALWAYS
, ppvContext
);
97 contentType
= CERT_QUERY_CONTENT_CERT
;
99 if (!ret
&& (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CRL
))
101 ret
= pCRLInterface
->addEncodedToStore(store
, X509_ASN_ENCODING
,
102 blob
->pbData
, blob
->cbData
, CERT_STORE_ADD_ALWAYS
, ppvContext
);
104 contentType
= CERT_QUERY_CONTENT_CRL
;
106 if (!ret
&& (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CTL
))
108 ret
= pCTLInterface
->addEncodedToStore(store
, X509_ASN_ENCODING
,
109 blob
->pbData
, blob
->cbData
, CERT_STORE_ADD_ALWAYS
, ppvContext
);
111 contentType
= CERT_QUERY_CONTENT_CTL
;
115 if (pdwMsgAndCertEncodingType
)
116 *pdwMsgAndCertEncodingType
= X509_ASN_ENCODING
;
118 *pdwContentType
= contentType
;
120 *phCertStore
= CertDuplicateStore(store
);
122 CertCloseStore(store
, 0);
123 if (blob
== &fileBlob
)
124 CryptMemFree(blob
->pbData
);
125 TRACE("returning %d\n", ret
);
129 static BOOL
CRYPT_QuerySerializedContextObject(DWORD dwObjectType
,
130 const void *pvObject
, DWORD dwExpectedContentTypeFlags
,
131 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
132 HCERTSTORE
*phCertStore
, const void **ppvContext
)
135 const CERT_BLOB
*blob
;
136 const WINE_CONTEXT_INTERFACE
*contextInterface
= NULL
;
141 switch (dwObjectType
)
143 case CERT_QUERY_OBJECT_FILE
:
144 /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so
145 * just read the file directly
147 ret
= CRYPT_ReadBlobFromFile((LPCWSTR
)pvObject
, &fileBlob
);
150 case CERT_QUERY_OBJECT_BLOB
:
151 blob
= (const CERT_BLOB
*)pvObject
;
155 SetLastError(E_INVALIDARG
); /* FIXME: is this the correct error? */
161 context
= CRYPT_ReadSerializedElement(blob
->pbData
, blob
->cbData
,
162 CERT_STORE_ALL_CONTEXT_FLAG
, &contextType
);
165 DWORD contentType
, certStoreOffset
;
170 case CERT_STORE_CERTIFICATE_CONTEXT
:
171 contextInterface
= pCertInterface
;
172 contentType
= CERT_QUERY_CONTENT_SERIALIZED_CERT
;
173 certStoreOffset
= offsetof(CERT_CONTEXT
, hCertStore
);
174 if (!(dwExpectedContentTypeFlags
&
175 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
))
177 SetLastError(ERROR_INVALID_DATA
);
182 case CERT_STORE_CRL_CONTEXT
:
183 contextInterface
= pCRLInterface
;
184 contentType
= CERT_QUERY_CONTENT_SERIALIZED_CRL
;
185 certStoreOffset
= offsetof(CRL_CONTEXT
, hCertStore
);
186 if (!(dwExpectedContentTypeFlags
&
187 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
))
189 SetLastError(ERROR_INVALID_DATA
);
194 case CERT_STORE_CTL_CONTEXT
:
195 contextInterface
= pCTLInterface
;
196 contentType
= CERT_QUERY_CONTENT_SERIALIZED_CTL
;
197 certStoreOffset
= offsetof(CTL_CONTEXT
, hCertStore
);
198 if (!(dwExpectedContentTypeFlags
&
199 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
))
201 SetLastError(ERROR_INVALID_DATA
);
207 SetLastError(ERROR_INVALID_DATA
);
211 if (pdwMsgAndCertEncodingType
)
212 *pdwMsgAndCertEncodingType
= X509_ASN_ENCODING
;
214 *pdwContentType
= contentType
;
216 *phCertStore
= CertDuplicateStore(
217 *(HCERTSTORE
*)((const BYTE
*)context
+ certStoreOffset
));
219 *ppvContext
= contextInterface
->duplicate(context
);
223 if (contextInterface
&& context
)
224 contextInterface
->free(context
);
225 if (blob
== &fileBlob
)
226 CryptMemFree(blob
->pbData
);
227 TRACE("returning %d\n", ret
);
231 static BOOL
CRYPT_QuerySerializedStoreObject(DWORD dwObjectType
,
232 const void *pvObject
, DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
233 HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
)
235 LPCWSTR fileName
= (LPCWSTR
)pvObject
;
239 if (dwObjectType
!= CERT_QUERY_OBJECT_FILE
)
241 FIXME("unimplemented for non-file type %d\n", dwObjectType
);
242 SetLastError(E_INVALIDARG
); /* FIXME: is this the correct error? */
245 TRACE("%s\n", debugstr_w(fileName
));
246 file
= CreateFileW(fileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
247 OPEN_EXISTING
, 0, NULL
);
248 if (file
!= INVALID_HANDLE_VALUE
)
250 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
251 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
253 ret
= CRYPT_ReadSerializedStoreFromFile(file
, store
);
256 if (pdwMsgAndCertEncodingType
)
257 *pdwMsgAndCertEncodingType
= X509_ASN_ENCODING
;
259 *pdwContentType
= CERT_QUERY_CONTENT_SERIALIZED_STORE
;
261 *phCertStore
= CertDuplicateStore(store
);
263 CertCloseStore(store
, 0);
266 TRACE("returning %d\n", ret
);
270 /* Used to decode non-embedded messages */
271 static BOOL
CRYPT_QueryMessageObject(DWORD dwObjectType
, const void *pvObject
,
272 DWORD dwExpectedContentTypeFlags
, DWORD
*pdwMsgAndCertEncodingType
,
273 DWORD
*pdwContentType
, HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
)
276 const CERT_BLOB
*blob
;
278 HCRYPTMSG msg
= NULL
;
279 DWORD encodingType
= X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
;
281 switch (dwObjectType
)
283 case CERT_QUERY_OBJECT_FILE
:
284 /* This isn't an embedded PKCS7 message, so just read the file
287 ret
= CRYPT_ReadBlobFromFile((LPCWSTR
)pvObject
, &fileBlob
);
290 case CERT_QUERY_OBJECT_BLOB
:
291 blob
= (const CERT_BLOB
*)pvObject
;
295 SetLastError(E_INVALIDARG
); /* FIXME: is this the correct error? */
302 /* Try it first as a PKCS content info */
303 if ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
) ||
304 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
))
306 msg
= CryptMsgOpenToDecode(encodingType
, 0, 0, 0, NULL
, NULL
);
309 ret
= CryptMsgUpdate(msg
, blob
->pbData
, blob
->cbData
, TRUE
);
312 DWORD type
, len
= sizeof(type
);
314 ret
= CryptMsgGetParam(msg
, CMSG_TYPE_PARAM
, 0, &type
, &len
);
317 if ((dwExpectedContentTypeFlags
&
318 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
))
320 if (type
!= CMSG_SIGNED
)
322 SetLastError(ERROR_INVALID_DATA
);
325 else if (pdwContentType
)
326 *pdwContentType
= CERT_QUERY_CONTENT_PKCS7_SIGNED
;
328 else if ((dwExpectedContentTypeFlags
&
329 CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
))
331 if (type
!= CMSG_DATA
)
333 SetLastError(ERROR_INVALID_DATA
);
336 else if (pdwContentType
)
337 *pdwContentType
= CERT_QUERY_CONTENT_PKCS7_UNSIGNED
;
348 /* Failing that, try explicitly typed messages */
350 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
))
352 msg
= CryptMsgOpenToDecode(encodingType
, 0, CMSG_SIGNED
, 0, NULL
, NULL
);
355 ret
= CryptMsgUpdate(msg
, blob
->pbData
, blob
->cbData
, TRUE
);
362 if (msg
&& pdwContentType
)
363 *pdwContentType
= CERT_QUERY_CONTENT_PKCS7_SIGNED
;
366 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
))
368 msg
= CryptMsgOpenToDecode(encodingType
, 0, CMSG_DATA
, 0, NULL
, NULL
);
371 ret
= CryptMsgUpdate(msg
, blob
->pbData
, blob
->cbData
, TRUE
);
378 if (msg
&& pdwContentType
)
379 *pdwContentType
= CERT_QUERY_CONTENT_PKCS7_UNSIGNED
;
381 if (pdwMsgAndCertEncodingType
)
382 *pdwMsgAndCertEncodingType
= encodingType
;
388 *phCertStore
= CertOpenStore(CERT_STORE_PROV_MSG
, encodingType
, 0,
391 if (blob
== &fileBlob
)
392 CryptMemFree(blob
->pbData
);
393 TRACE("returning %d\n", ret
);
397 static BOOL
CRYPT_QueryEmbeddedMessageObject(DWORD dwObjectType
,
398 const void *pvObject
, DWORD dwExpectedContentTypeFlags
,
399 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
400 HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
)
406 TRACE("%s\n", debugstr_w((LPCWSTR
)pvObject
));
408 if (dwObjectType
!= CERT_QUERY_OBJECT_FILE
)
410 FIXME("don't know what to do for type %d embedded signed messages\n",
412 SetLastError(E_INVALIDARG
);
415 file
= CreateFileW((LPCWSTR
)pvObject
, GENERIC_READ
, FILE_SHARE_READ
,
416 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
417 if (file
!= INVALID_HANDLE_VALUE
)
419 ret
= CryptSIPRetrieveSubjectGuid((LPCWSTR
)pvObject
, file
, &subject
);
422 SIP_DISPATCH_INFO sip
;
424 memset(&sip
, 0, sizeof(sip
));
425 sip
.cbSize
= sizeof(sip
);
426 ret
= CryptSIPLoad(&subject
, 0, &sip
);
429 SIP_SUBJECTINFO subjectInfo
;
433 memset(&subjectInfo
, 0, sizeof(subjectInfo
));
434 subjectInfo
.cbSize
= sizeof(subjectInfo
);
435 subjectInfo
.pgSubjectType
= &subject
;
436 subjectInfo
.hFile
= file
;
437 subjectInfo
.pwsFileName
= (LPCWSTR
)pvObject
;
438 ret
= sip
.pfGet(&subjectInfo
, &encodingType
, 0, &blob
.cbData
,
442 blob
.pbData
= CryptMemAlloc(blob
.cbData
);
445 ret
= sip
.pfGet(&subjectInfo
, &encodingType
, 0,
446 &blob
.cbData
, blob
.pbData
);
449 ret
= CRYPT_QueryMessageObject(
450 CERT_QUERY_OBJECT_BLOB
, &blob
,
451 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
,
452 pdwMsgAndCertEncodingType
, NULL
, phCertStore
,
454 if (ret
&& pdwContentType
)
456 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
;
458 CryptMemFree(blob
.pbData
);
462 SetLastError(ERROR_OUTOFMEMORY
);
470 TRACE("returning %d\n", ret
);
474 BOOL WINAPI
CryptQueryObject(DWORD dwObjectType
, const void *pvObject
,
475 DWORD dwExpectedContentTypeFlags
, DWORD dwExpectedFormatTypeFlags
,
476 DWORD dwFlags
, DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
477 DWORD
*pdwFormatType
, HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
,
478 const void **ppvContext
)
480 static const DWORD unimplementedTypes
=
481 CERT_QUERY_CONTENT_FLAG_PKCS10
| CERT_QUERY_CONTENT_FLAG_PFX
|
482 CERT_QUERY_CONTENT_FLAG_CERT_PAIR
;
485 TRACE("(%08x, %p, %08x, %08x, %08x, %p, %p, %p, %p, %p, %p)\n",
486 dwObjectType
, pvObject
, dwExpectedContentTypeFlags
,
487 dwExpectedFormatTypeFlags
, dwFlags
, pdwMsgAndCertEncodingType
,
488 pdwContentType
, pdwFormatType
, phCertStore
, phMsg
, ppvContext
);
490 if (dwExpectedContentTypeFlags
& unimplementedTypes
)
491 WARN("unimplemented for types %08x\n",
492 dwExpectedContentTypeFlags
& unimplementedTypes
);
493 if (!(dwExpectedFormatTypeFlags
& CERT_QUERY_FORMAT_FLAG_BINARY
))
495 FIXME("unimplemented for anything but binary\n");
496 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
500 *pdwFormatType
= CERT_QUERY_FORMAT_BINARY
;
510 if ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CERT
) ||
511 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CRL
) ||
512 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CTL
))
514 ret
= CRYPT_QueryContextObject(dwObjectType
, pvObject
,
515 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
516 phCertStore
, ppvContext
);
519 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
))
521 ret
= CRYPT_QuerySerializedStoreObject(dwObjectType
, pvObject
,
522 pdwMsgAndCertEncodingType
, pdwContentType
, phCertStore
, phMsg
);
525 ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
) ||
526 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
) ||
527 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
)))
529 ret
= CRYPT_QuerySerializedContextObject(dwObjectType
, pvObject
,
530 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
531 phCertStore
, ppvContext
);
534 ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
) ||
535 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
)))
537 ret
= CRYPT_QueryMessageObject(dwObjectType
, pvObject
,
538 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
542 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED
))
544 ret
= CRYPT_QueryEmbeddedMessageObject(dwObjectType
, pvObject
,
545 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
548 TRACE("returning %d\n", ret
);