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
, &len
);
373 WIN_CERTIFICATE
*winCert
= HeapAlloc(GetProcessHeap(), 0, len
);
377 ret
= ImageGetCertificateData(file
, 0, winCert
, &len
);
380 CERT_BLOB blob
= { winCert
->dwLength
,
381 winCert
->bCertificate
};
383 ret
= CRYPT_QueryMessageObject(CERT_QUERY_OBJECT_BLOB
,
384 &blob
, CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
,
385 pdwMsgAndCertEncodingType
, NULL
, phCertStore
, phMsg
);
386 if (ret
&& pdwContentType
)
387 *pdwContentType
= CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
;
389 HeapFree(GetProcessHeap(), 0, winCert
);
394 TRACE("returning %d\n", ret
);
398 BOOL WINAPI
CryptQueryObject(DWORD dwObjectType
, const void *pvObject
,
399 DWORD dwExpectedContentTypeFlags
, DWORD dwExpectedFormatTypeFlags
,
400 DWORD dwFlags
, DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
401 DWORD
*pdwFormatType
, HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
,
402 const void **ppvContext
)
404 static const DWORD unimplementedTypes
=
405 CERT_QUERY_CONTENT_FLAG_PKCS10
| CERT_QUERY_CONTENT_FLAG_PFX
|
406 CERT_QUERY_CONTENT_FLAG_CERT_PAIR
;
409 TRACE("(%08x, %p, %08x, %08x, %08x, %p, %p, %p, %p, %p, %p)\n",
410 dwObjectType
, pvObject
, dwExpectedContentTypeFlags
,
411 dwExpectedFormatTypeFlags
, dwFlags
, pdwMsgAndCertEncodingType
,
412 pdwContentType
, pdwFormatType
, phCertStore
, phMsg
, ppvContext
);
414 if (dwExpectedContentTypeFlags
& unimplementedTypes
)
415 WARN("unimplemented for types %08x\n",
416 dwExpectedContentTypeFlags
& unimplementedTypes
);
417 if (!(dwExpectedFormatTypeFlags
& CERT_QUERY_FORMAT_FLAG_BINARY
))
419 FIXME("unimplemented for anything but binary\n");
420 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
424 *pdwFormatType
= CERT_QUERY_FORMAT_BINARY
;
434 if ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CERT
) ||
435 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CRL
) ||
436 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CTL
))
438 ret
= CRYPT_QueryContextObject(dwObjectType
, pvObject
,
439 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
440 phCertStore
, ppvContext
);
443 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
))
445 ret
= CRYPT_QuerySerializedStoreObject(dwObjectType
, pvObject
,
446 pdwMsgAndCertEncodingType
, pdwContentType
, phCertStore
, phMsg
);
449 ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
) ||
450 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
) ||
451 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
)))
453 ret
= CRYPT_QuerySerializedContextObject(dwObjectType
, pvObject
,
454 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
455 phCertStore
, ppvContext
);
458 ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
) ||
459 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
)))
461 ret
= CRYPT_QueryMessageObject(dwObjectType
, pvObject
,
462 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
466 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED
))
468 ret
= CRYPT_QueryEmbeddedMessageObject(dwObjectType
, pvObject
,
469 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
472 TRACE("returning %d\n", ret
);