crypt32: Implement CertDeleteCTLFromStore.
[wine/hacks.git] / dlls / crypt32 / ctl.c
blob864f56d44db2ca95e724cd0630223dfd74b18f5c
1 /*
2 * Copyright 2008 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <assert.h>
21 #include <stdarg.h>
23 #define NONAMELESSUNION
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wincrypt.h"
27 #include "wine/debug.h"
28 #include "crypt32_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
32 BOOL WINAPI CertAddEncodedCTLToStore(HCERTSTORE hCertStore,
33 DWORD dwMsgAndCertEncodingType, const BYTE *pbCtlEncoded, DWORD cbCtlEncoded,
34 DWORD dwAddDisposition, PCCTL_CONTEXT *ppCtlContext)
36 PCCTL_CONTEXT ctl = CertCreateCTLContext(dwMsgAndCertEncodingType,
37 pbCtlEncoded, cbCtlEncoded);
38 BOOL ret;
40 TRACE("(%p, %08x, %p, %d, %08x, %p)\n", hCertStore,
41 dwMsgAndCertEncodingType, pbCtlEncoded, cbCtlEncoded, dwAddDisposition,
42 ppCtlContext);
44 if (ctl)
46 ret = CertAddCTLContextToStore(hCertStore, ctl, dwAddDisposition,
47 ppCtlContext);
48 CertFreeCTLContext(ctl);
50 else
51 ret = FALSE;
52 return ret;
55 PCCTL_CONTEXT WINAPI CertEnumCTLsInStore(HCERTSTORE hCertStore,
56 PCCTL_CONTEXT pPrev)
58 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
59 PCCTL_CONTEXT ret;
61 TRACE("(%p, %p)\n", hCertStore, pPrev);
62 if (!hCertStore)
63 ret = NULL;
64 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
65 ret = NULL;
66 else
67 ret = (PCCTL_CONTEXT)hcs->ctls.enumContext(hcs, (void *)pPrev);
68 return ret;
71 BOOL WINAPI CertDeleteCTLFromStore(PCCTL_CONTEXT pCtlContext)
73 BOOL ret;
75 TRACE("(%p)\n", pCtlContext);
77 if (!pCtlContext)
78 ret = TRUE;
79 else if (!pCtlContext->hCertStore)
81 ret = TRUE;
82 CertFreeCTLContext(pCtlContext);
84 else
86 PWINECRYPT_CERTSTORE hcs =
87 (PWINECRYPT_CERTSTORE)pCtlContext->hCertStore;
89 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
90 ret = FALSE;
91 else
92 ret = hcs->ctls.deleteContext(hcs, (void *)pCtlContext);
93 CertFreeCTLContext(pCtlContext);
95 return ret;
98 PCCTL_CONTEXT WINAPI CertCreateCTLContext(DWORD dwMsgAndCertEncodingType,
99 const BYTE *pbCtlEncoded, DWORD cbCtlEncoded)
101 PCTL_CONTEXT ctl = NULL;
102 HCRYPTMSG msg;
103 BOOL ret;
104 BYTE *content = NULL;
105 DWORD contentSize = 0, size;
106 PCTL_INFO ctlInfo = NULL;
108 TRACE("(%08x, %p, %d)\n", dwMsgAndCertEncodingType, pbCtlEncoded,
109 cbCtlEncoded);
111 if (GET_CERT_ENCODING_TYPE(dwMsgAndCertEncodingType) != X509_ASN_ENCODING)
113 SetLastError(E_INVALIDARG);
114 return NULL;
116 if (!pbCtlEncoded || !cbCtlEncoded)
118 SetLastError(ERROR_INVALID_DATA);
119 return NULL;
121 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, 0,
122 0, NULL, NULL);
123 if (!msg)
124 return NULL;
125 ret = CryptMsgUpdate(msg, pbCtlEncoded, cbCtlEncoded, TRUE);
126 if (!ret)
128 SetLastError(ERROR_INVALID_DATA);
129 goto end;
131 /* Check that it's really a CTL */
132 ret = CryptMsgGetParam(msg, CMSG_INNER_CONTENT_TYPE_PARAM, 0, NULL, &size);
133 if (ret)
135 char *innerContent = CryptMemAlloc(size);
137 if (innerContent)
139 ret = CryptMsgGetParam(msg, CMSG_INNER_CONTENT_TYPE_PARAM, 0,
140 innerContent, &size);
141 if (ret)
143 if (strcmp(innerContent, szOID_CTL))
145 SetLastError(ERROR_INVALID_DATA);
146 ret = FALSE;
149 CryptMemFree(innerContent);
151 else
153 SetLastError(ERROR_OUTOFMEMORY);
154 ret = FALSE;
157 if (!ret)
158 goto end;
159 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &contentSize);
160 if (!ret)
161 goto end;
162 content = CryptMemAlloc(contentSize);
163 if (content)
165 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, content,
166 &contentSize);
167 if (ret)
169 ret = CryptDecodeObjectEx(dwMsgAndCertEncodingType, PKCS_CTL,
170 content, contentSize, CRYPT_DECODE_ALLOC_FLAG, NULL,
171 (BYTE *)&ctlInfo, &size);
172 if (ret)
174 ctl = (PCTL_CONTEXT)Context_CreateDataContext(
175 sizeof(CTL_CONTEXT));
176 if (ctl)
178 BYTE *data = CryptMemAlloc(cbCtlEncoded);
180 if (data)
182 memcpy(data, pbCtlEncoded, cbCtlEncoded);
183 ctl->dwMsgAndCertEncodingType =
184 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
185 ctl->pbCtlEncoded = data;
186 ctl->cbCtlEncoded = cbCtlEncoded;
187 ctl->pCtlInfo = ctlInfo;
188 ctl->hCertStore = NULL;
189 ctl->hCryptMsg = msg;
190 ctl->pbCtlContext = content;
191 ctl->cbCtlContext = contentSize;
193 else
195 SetLastError(ERROR_OUTOFMEMORY);
196 ret = FALSE;
199 else
201 SetLastError(ERROR_OUTOFMEMORY);
202 ret = FALSE;
207 else
209 SetLastError(ERROR_OUTOFMEMORY);
210 ret = FALSE;
213 end:
214 if (!ret)
216 CryptMemFree(ctl);
217 ctl = NULL;
218 LocalFree(ctlInfo);
219 CryptMemFree(content);
220 CryptMsgClose(msg);
222 return (PCCTL_CONTEXT)ctl;
225 PCCTL_CONTEXT WINAPI CertDuplicateCTLContext(PCCTL_CONTEXT pCtlContext)
227 TRACE("(%p)\n", pCtlContext);
228 Context_AddRef((void *)pCtlContext, sizeof(CTL_CONTEXT));
229 return pCtlContext;
232 static void CTLDataContext_Free(void *context)
234 PCTL_CONTEXT ctlContext = (PCTL_CONTEXT)context;
236 CryptMsgClose(ctlContext->hCryptMsg);
237 CryptMemFree(ctlContext->pbCtlEncoded);
238 CryptMemFree(ctlContext->pbCtlContext);
239 LocalFree(ctlContext->pCtlInfo);
242 BOOL WINAPI CertFreeCTLContext(PCCTL_CONTEXT pCTLContext)
244 TRACE("(%p)\n", pCTLContext);
246 if (pCTLContext)
247 Context_Release((void *)pCTLContext, sizeof(CTL_CONTEXT),
248 CTLDataContext_Free);
249 return TRUE;
252 DWORD WINAPI CertEnumCTLContextProperties(PCCTL_CONTEXT pCTLContext,
253 DWORD dwPropId)
255 PCONTEXT_PROPERTY_LIST properties = Context_GetProperties(
256 (void *)pCTLContext, sizeof(CTL_CONTEXT));
257 DWORD ret;
259 TRACE("(%p, %d)\n", pCTLContext, dwPropId);
261 if (properties)
262 ret = ContextPropertyList_EnumPropIDs(properties, dwPropId);
263 else
264 ret = 0;
265 return ret;
268 static BOOL CTLContext_SetProperty(PCCTL_CONTEXT context, DWORD dwPropId,
269 DWORD dwFlags, const void *pvData);
271 static BOOL CTLContext_GetHashProp(PCCTL_CONTEXT context, DWORD dwPropId,
272 ALG_ID algID, const BYTE *toHash, DWORD toHashLen, void *pvData,
273 DWORD *pcbData)
275 BOOL ret = CryptHashCertificate(0, algID, 0, toHash, toHashLen, pvData,
276 pcbData);
277 if (ret)
279 CRYPT_DATA_BLOB blob = { *pcbData, pvData };
281 ret = CTLContext_SetProperty(context, dwPropId, 0, &blob);
283 return ret;
286 static BOOL CTLContext_GetProperty(PCCTL_CONTEXT context, DWORD dwPropId,
287 void *pvData, DWORD *pcbData)
289 PCONTEXT_PROPERTY_LIST properties =
290 Context_GetProperties(context, sizeof(CTL_CONTEXT));
291 BOOL ret;
292 CRYPT_DATA_BLOB blob;
294 TRACE("(%p, %d, %p, %p)\n", context, dwPropId, pvData, pcbData);
296 if (properties)
297 ret = ContextPropertyList_FindProperty(properties, dwPropId, &blob);
298 else
299 ret = FALSE;
300 if (ret)
302 if (!pvData)
303 *pcbData = blob.cbData;
304 else if (*pcbData < blob.cbData)
306 SetLastError(ERROR_MORE_DATA);
307 *pcbData = blob.cbData;
308 ret = FALSE;
310 else
312 memcpy(pvData, blob.pbData, blob.cbData);
313 *pcbData = blob.cbData;
316 else
318 /* Implicit properties */
319 switch (dwPropId)
321 case CERT_SHA1_HASH_PROP_ID:
322 ret = CTLContext_GetHashProp(context, dwPropId, CALG_SHA1,
323 context->pbCtlEncoded, context->cbCtlEncoded, pvData, pcbData);
324 break;
325 case CERT_MD5_HASH_PROP_ID:
326 ret = CTLContext_GetHashProp(context, dwPropId, CALG_MD5,
327 context->pbCtlEncoded, context->cbCtlEncoded, pvData, pcbData);
328 break;
329 default:
330 SetLastError(CRYPT_E_NOT_FOUND);
333 TRACE("returning %d\n", ret);
334 return ret;
337 BOOL WINAPI CertGetCTLContextProperty(PCCTL_CONTEXT pCTLContext,
338 DWORD dwPropId, void *pvData, DWORD *pcbData)
340 BOOL ret;
342 TRACE("(%p, %d, %p, %p)\n", pCTLContext, dwPropId, pvData, pcbData);
344 switch (dwPropId)
346 case 0:
347 case CERT_CERT_PROP_ID:
348 case CERT_CRL_PROP_ID:
349 case CERT_CTL_PROP_ID:
350 SetLastError(E_INVALIDARG);
351 ret = FALSE;
352 break;
353 case CERT_ACCESS_STATE_PROP_ID:
354 if (!pvData)
356 *pcbData = sizeof(DWORD);
357 ret = TRUE;
359 else if (*pcbData < sizeof(DWORD))
361 SetLastError(ERROR_MORE_DATA);
362 *pcbData = sizeof(DWORD);
363 ret = FALSE;
365 else
367 if (pCTLContext->hCertStore)
368 ret = CertGetStoreProperty(pCTLContext->hCertStore, dwPropId,
369 pvData, pcbData);
370 else
371 *(DWORD *)pvData = 0;
372 ret = TRUE;
374 break;
375 default:
376 ret = CTLContext_GetProperty(pCTLContext, dwPropId, pvData,
377 pcbData);
379 return ret;
382 static BOOL CTLContext_SetProperty(PCCTL_CONTEXT context, DWORD dwPropId,
383 DWORD dwFlags, const void *pvData)
385 PCONTEXT_PROPERTY_LIST properties =
386 Context_GetProperties(context, sizeof(CTL_CONTEXT));
387 BOOL ret;
389 TRACE("(%p, %d, %08x, %p)\n", context, dwPropId, dwFlags, pvData);
391 if (!properties)
392 ret = FALSE;
393 else if (!pvData)
395 ContextPropertyList_RemoveProperty(properties, dwPropId);
396 ret = TRUE;
398 else
400 switch (dwPropId)
402 case CERT_AUTO_ENROLL_PROP_ID:
403 case CERT_CTL_USAGE_PROP_ID: /* same as CERT_ENHKEY_USAGE_PROP_ID */
404 case CERT_DESCRIPTION_PROP_ID:
405 case CERT_FRIENDLY_NAME_PROP_ID:
406 case CERT_HASH_PROP_ID:
407 case CERT_KEY_IDENTIFIER_PROP_ID:
408 case CERT_MD5_HASH_PROP_ID:
409 case CERT_NEXT_UPDATE_LOCATION_PROP_ID:
410 case CERT_PUBKEY_ALG_PARA_PROP_ID:
411 case CERT_PVK_FILE_PROP_ID:
412 case CERT_SIGNATURE_HASH_PROP_ID:
413 case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID:
414 case CERT_SUBJECT_NAME_MD5_HASH_PROP_ID:
415 case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID:
416 case CERT_ENROLLMENT_PROP_ID:
417 case CERT_CROSS_CERT_DIST_POINTS_PROP_ID:
418 case CERT_RENEWAL_PROP_ID:
420 PCRYPT_DATA_BLOB blob = (PCRYPT_DATA_BLOB)pvData;
422 ret = ContextPropertyList_SetProperty(properties, dwPropId,
423 blob->pbData, blob->cbData);
424 break;
426 case CERT_DATE_STAMP_PROP_ID:
427 ret = ContextPropertyList_SetProperty(properties, dwPropId,
428 (const BYTE *)pvData, sizeof(FILETIME));
429 break;
430 default:
431 FIXME("%d: stub\n", dwPropId);
432 ret = FALSE;
435 TRACE("returning %d\n", ret);
436 return ret;
439 BOOL WINAPI CertSetCTLContextProperty(PCCTL_CONTEXT pCTLContext,
440 DWORD dwPropId, DWORD dwFlags, const void *pvData)
442 BOOL ret;
444 TRACE("(%p, %d, %08x, %p)\n", pCTLContext, dwPropId, dwFlags, pvData);
446 /* Handle special cases for "read-only"/invalid prop IDs. Windows just
447 * crashes on most of these, I'll be safer.
449 switch (dwPropId)
451 case 0:
452 case CERT_ACCESS_STATE_PROP_ID:
453 case CERT_CERT_PROP_ID:
454 case CERT_CRL_PROP_ID:
455 case CERT_CTL_PROP_ID:
456 SetLastError(E_INVALIDARG);
457 return FALSE;
459 ret = CTLContext_SetProperty(pCTLContext, dwPropId, dwFlags, pvData);
460 TRACE("returning %d\n", ret);
461 return ret;