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_ReadSerializedFile(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 if (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
)
304 msg
= CryptMsgOpenToDecode(encodingType
, 0, CMSG_SIGNED
, 0, NULL
, NULL
);
307 ret
= CryptMsgUpdate(msg
, blob
->pbData
, blob
->cbData
, TRUE
);
314 if (msg
&& pdwContentType
)
315 *pdwContentType
= CERT_QUERY_CONTENT_PKCS7_SIGNED
;
318 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
))
320 msg
= CryptMsgOpenToDecode(encodingType
, 0, CMSG_DATA
, 0, NULL
, NULL
);
323 ret
= CryptMsgUpdate(msg
, blob
->pbData
, blob
->cbData
, TRUE
);
330 if (msg
&& pdwContentType
)
331 *pdwContentType
= CERT_QUERY_CONTENT_PKCS7_UNSIGNED
;
333 if (pdwMsgAndCertEncodingType
)
334 *pdwMsgAndCertEncodingType
= encodingType
;
340 *phCertStore
= CertOpenStore(CERT_STORE_PROV_MSG
, encodingType
, 0,
343 if (blob
== &fileBlob
)
344 CryptMemFree(blob
->pbData
);
345 TRACE("returning %d\n", ret
);
349 static BOOL
CRYPT_QueryEmbeddedMessageObject(DWORD dwObjectType
,
350 const void *pvObject
, DWORD dwExpectedContentTypeFlags
,
351 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
352 HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
)
357 if (dwObjectType
!= CERT_QUERY_OBJECT_FILE
)
359 FIXME("don't know what to do for type %d embedded signed messages\n",
361 SetLastError(E_INVALIDARG
);
364 file
= CreateFileW((LPCWSTR
)pvObject
, GENERIC_READ
, FILE_SHARE_READ
,
365 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
366 if (file
!= INVALID_HANDLE_VALUE
)
370 ret
= ImageGetCertificateData(file
, 0, NULL
, &blob
.cbData
);
373 blob
.pbData
= HeapAlloc(GetProcessHeap(), 0, blob
.cbData
);
376 ret
= ImageGetCertificateData(file
, 0,
377 (WIN_CERTIFICATE
*)blob
.pbData
, &blob
.cbData
);
380 ret
= CRYPT_QueryMessageObject(CERT_QUERY_OBJECT_BLOB
,
381 &blob
, CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
,
382 pdwMsgAndCertEncodingType
, NULL
, phCertStore
, phMsg
);
383 if (ret
&& pdwContentType
)
384 *pdwContentType
= CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
;
386 HeapFree(GetProcessHeap(), 0, blob
.pbData
);
391 TRACE("returning %d\n", ret
);
395 BOOL WINAPI
CryptQueryObject(DWORD dwObjectType
, const void *pvObject
,
396 DWORD dwExpectedContentTypeFlags
, DWORD dwExpectedFormatTypeFlags
,
397 DWORD dwFlags
, DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
398 DWORD
*pdwFormatType
, HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
,
399 const void **ppvContext
)
401 static const DWORD unimplementedTypes
=
402 CERT_QUERY_CONTENT_FLAG_PKCS10
| CERT_QUERY_CONTENT_FLAG_PFX
|
403 CERT_QUERY_CONTENT_FLAG_CERT_PAIR
;
406 TRACE("(%08x, %p, %08x, %08x, %08x, %p, %p, %p, %p, %p, %p)\n",
407 dwObjectType
, pvObject
, dwExpectedContentTypeFlags
,
408 dwExpectedFormatTypeFlags
, dwFlags
, pdwMsgAndCertEncodingType
,
409 pdwContentType
, pdwFormatType
, phCertStore
, phMsg
, ppvContext
);
411 if (dwExpectedContentTypeFlags
& unimplementedTypes
)
412 WARN("unimplemented for types %08x\n",
413 dwExpectedContentTypeFlags
& unimplementedTypes
);
414 if (!(dwExpectedFormatTypeFlags
& CERT_QUERY_FORMAT_FLAG_BINARY
))
416 FIXME("unimplemented for anything but binary\n");
417 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
421 *pdwFormatType
= CERT_QUERY_FORMAT_BINARY
;
431 if ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CERT
) ||
432 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CRL
) ||
433 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CTL
))
435 ret
= CRYPT_QueryContextObject(dwObjectType
, pvObject
,
436 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
437 phCertStore
, ppvContext
);
440 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
))
442 ret
= CRYPT_QuerySerializedStoreObject(dwObjectType
, pvObject
,
443 pdwMsgAndCertEncodingType
, pdwContentType
, phCertStore
, phMsg
);
446 ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
) ||
447 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
) ||
448 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
)))
450 ret
= CRYPT_QuerySerializedContextObject(dwObjectType
, pvObject
,
451 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
452 phCertStore
, ppvContext
);
455 ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
) ||
456 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
)))
458 ret
= CRYPT_QueryMessageObject(dwObjectType
, pvObject
,
459 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
463 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED
))
465 ret
= CRYPT_QueryEmbeddedMessageObject(dwObjectType
, pvObject
,
466 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
469 TRACE("returning %d\n");