Convert remaining source files to utf-8.
[wine/multimedia.git] / dlls / crypt32 / object.c
blob05a6c5f20535b062cc0abdb1faacaf90c2f7a242
1 /*
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
20 #include <stdarg.h>
21 #include "windef.h"
22 #include "winbase.h"
23 #include "wincrypt.h"
24 #include "mssip.h"
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)
32 BOOL ret = FALSE;
33 HANDLE file;
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)
41 ret = TRUE;
42 blob->cbData = GetFileSize(file, NULL);
43 if (blob->cbData)
45 blob->pbData = CryptMemAlloc(blob->cbData);
46 if (blob->pbData)
48 DWORD read;
50 ret = ReadFile(file, blob->pbData, blob->cbData, &read, NULL);
53 CloseHandle(file);
55 TRACE("returning %d\n", ret);
56 return ret;
59 static BOOL CRYPT_QueryContextObject(DWORD dwObjectType, const void *pvObject,
60 DWORD dwExpectedContentTypeFlags, DWORD *pdwMsgAndCertEncodingType,
61 DWORD *pdwContentType, HCERTSTORE *phCertStore, const void **ppvContext)
63 CERT_BLOB fileBlob;
64 const CERT_BLOB *blob;
65 HCERTSTORE store;
66 DWORD contentType;
67 BOOL ret;
69 switch (dwObjectType)
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);
76 blob = &fileBlob;
77 break;
78 case CERT_QUERY_OBJECT_BLOB:
79 blob = (const CERT_BLOB *)pvObject;
80 ret = TRUE;
81 break;
82 default:
83 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
84 ret = FALSE;
86 if (!ret)
87 return FALSE;
89 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
90 CERT_STORE_CREATE_NEW_FLAG, NULL);
91 ret = FALSE;
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);
96 if (ret)
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);
103 if (ret)
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);
110 if (ret)
111 contentType = CERT_QUERY_CONTENT_CTL;
113 if (ret)
115 if (pdwMsgAndCertEncodingType)
116 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING;
117 if (pdwContentType)
118 *pdwContentType = contentType;
119 if (phCertStore)
120 *phCertStore = CertDuplicateStore(store);
122 CertCloseStore(store, 0);
123 if (blob == &fileBlob)
124 CryptMemFree(blob->pbData);
125 TRACE("returning %d\n", ret);
126 return 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)
134 CERT_BLOB fileBlob;
135 const CERT_BLOB *blob;
136 const WINE_CONTEXT_INTERFACE *contextInterface = NULL;
137 const void *context;
138 DWORD contextType;
139 BOOL ret;
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);
148 blob = &fileBlob;
149 break;
150 case CERT_QUERY_OBJECT_BLOB:
151 blob = (const CERT_BLOB *)pvObject;
152 ret = TRUE;
153 break;
154 default:
155 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
156 ret = FALSE;
158 if (!ret)
159 return FALSE;
161 context = CRYPT_ReadSerializedElement(blob->pbData, blob->cbData,
162 CERT_STORE_ALL_CONTEXT_FLAG, &contextType);
163 if (context)
165 DWORD contentType, certStoreOffset;
167 ret = TRUE;
168 switch (contextType)
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);
178 ret = FALSE;
179 goto end;
181 break;
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);
190 ret = FALSE;
191 goto end;
193 break;
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);
202 ret = FALSE;
203 goto end;
205 break;
206 default:
207 SetLastError(ERROR_INVALID_DATA);
208 ret = FALSE;
209 goto end;
211 if (pdwMsgAndCertEncodingType)
212 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING;
213 if (pdwContentType)
214 *pdwContentType = contentType;
215 if (phCertStore)
216 *phCertStore = CertDuplicateStore(
217 *(HCERTSTORE *)((const BYTE *)context + certStoreOffset));
218 if (ppvContext)
219 *ppvContext = contextInterface->duplicate(context);
222 end:
223 if (contextInterface && context)
224 contextInterface->free(context);
225 if (blob == &fileBlob)
226 CryptMemFree(blob->pbData);
227 TRACE("returning %d\n", ret);
228 return 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;
236 HANDLE file;
237 BOOL ret = FALSE;
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? */
243 return FALSE;
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);
254 if (ret)
256 if (pdwMsgAndCertEncodingType)
257 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING;
258 if (pdwContentType)
259 *pdwContentType = CERT_QUERY_CONTENT_SERIALIZED_STORE;
260 if (phCertStore)
261 *phCertStore = CertDuplicateStore(store);
263 CertCloseStore(store, 0);
264 CloseHandle(file);
266 TRACE("returning %d\n", ret);
267 return 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)
275 CERT_BLOB fileBlob;
276 const CERT_BLOB *blob;
277 BOOL ret;
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
285 * directly
287 ret = CRYPT_ReadBlobFromFile((LPCWSTR)pvObject, &fileBlob);
288 blob = &fileBlob;
289 break;
290 case CERT_QUERY_OBJECT_BLOB:
291 blob = (const CERT_BLOB *)pvObject;
292 ret = TRUE;
293 break;
294 default:
295 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
296 ret = FALSE;
298 if (!ret)
299 return FALSE;
301 ret = FALSE;
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);
307 if (msg)
309 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE);
310 if (ret)
312 DWORD type, len = sizeof(type);
314 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &len);
315 if (ret)
317 if ((dwExpectedContentTypeFlags &
318 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED))
320 if (type != CMSG_SIGNED)
322 SetLastError(ERROR_INVALID_DATA);
323 ret = FALSE;
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);
334 ret = FALSE;
336 else if (pdwContentType)
337 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_UNSIGNED;
341 if (!ret)
343 CryptMsgClose(msg);
344 msg = NULL;
348 /* Failing that, try explicitly typed messages */
349 if (!ret &&
350 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED))
352 msg = CryptMsgOpenToDecode(encodingType, 0, CMSG_SIGNED, 0, NULL, NULL);
353 if (msg)
355 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE);
356 if (!ret)
358 CryptMsgClose(msg);
359 msg = NULL;
362 if (msg && pdwContentType)
363 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_SIGNED;
365 if (!ret &&
366 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED))
368 msg = CryptMsgOpenToDecode(encodingType, 0, CMSG_DATA, 0, NULL, NULL);
369 if (msg)
371 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE);
372 if (!ret)
374 CryptMsgClose(msg);
375 msg = NULL;
378 if (msg && pdwContentType)
379 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_UNSIGNED;
381 if (pdwMsgAndCertEncodingType)
382 *pdwMsgAndCertEncodingType = encodingType;
383 if (msg)
385 if (phMsg)
386 *phMsg = msg;
387 if (phCertStore)
388 *phCertStore = CertOpenStore(CERT_STORE_PROV_MSG, encodingType, 0,
389 0, msg);
391 if (blob == &fileBlob)
392 CryptMemFree(blob->pbData);
393 TRACE("returning %d\n", ret);
394 return ret;
397 static BOOL CRYPT_QueryEmbeddedMessageObject(DWORD dwObjectType,
398 const void *pvObject, DWORD dwExpectedContentTypeFlags,
399 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
400 HCERTSTORE *phCertStore, HCRYPTMSG *phMsg)
402 HANDLE file;
403 GUID subject;
404 BOOL ret = FALSE;
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",
411 dwObjectType);
412 SetLastError(E_INVALIDARG);
413 return FALSE;
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);
420 if (ret)
422 SIP_DISPATCH_INFO sip;
424 memset(&sip, 0, sizeof(sip));
425 sip.cbSize = sizeof(sip);
426 ret = CryptSIPLoad(&subject, 0, &sip);
427 if (ret)
429 SIP_SUBJECTINFO subjectInfo;
430 CERT_BLOB blob;
431 DWORD encodingType;
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,
439 NULL);
440 if (ret)
442 blob.pbData = CryptMemAlloc(blob.cbData);
443 if (blob.pbData)
445 ret = sip.pfGet(&subjectInfo, &encodingType, 0,
446 &blob.cbData, blob.pbData);
447 if (ret)
449 ret = CRYPT_QueryMessageObject(
450 CERT_QUERY_OBJECT_BLOB, &blob,
451 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED,
452 pdwMsgAndCertEncodingType, NULL, phCertStore,
453 phMsg);
454 if (ret && pdwContentType)
455 *pdwContentType =
456 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED;
458 CryptMemFree(blob.pbData);
460 else
462 SetLastError(ERROR_OUTOFMEMORY);
463 ret = FALSE;
468 CloseHandle(file);
470 TRACE("returning %d\n", ret);
471 return 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;
483 BOOL ret = TRUE;
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);
497 return FALSE;
499 if (pdwFormatType)
500 *pdwFormatType = CERT_QUERY_FORMAT_BINARY;
502 if (phCertStore)
503 *phCertStore = NULL;
504 if (phMsg)
505 *phMsg = NULL;
506 if (ppvContext)
507 *ppvContext = NULL;
509 ret = FALSE;
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);
518 if (!ret &&
519 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE))
521 ret = CRYPT_QuerySerializedStoreObject(dwObjectType, pvObject,
522 pdwMsgAndCertEncodingType, pdwContentType, phCertStore, phMsg);
524 if (!ret &&
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);
533 if (!ret &&
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,
539 phCertStore, phMsg);
541 if (!ret &&
542 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED))
544 ret = CRYPT_QueryEmbeddedMessageObject(dwObjectType, pvObject,
545 dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType,
546 phCertStore, phMsg);
548 TRACE("returning %d\n", ret);
549 return ret;