Commit | Line | Data |
---|---|---|
429b1e1b JL |
1 | /* |
2 | * Copyright 2008 Juan Lang | |
3 | * | |
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. | |
8 | * | |
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. | |
13 | * | |
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 | |
17 | * | |
18 | */ | |
19 | ||
20 | #include <assert.h> | |
21 | #include <stdarg.h> | |
22 | ||
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" | |
29 | ||
30 | WINE_DEFAULT_DEBUG_CHANNEL(crypt); | |
31 | ||
07de224b JL |
32 | #define CtlContext_CopyProperties(to, from) \ |
33 | Context_CopyProperties((to), (from), sizeof(CTL_CONTEXT)) | |
34 | ||
35 | BOOL WINAPI CertAddCTLContextToStore(HCERTSTORE hCertStore, | |
36 | PCCTL_CONTEXT pCtlContext, DWORD dwAddDisposition, | |
37 | PCCTL_CONTEXT* ppStoreContext) | |
38 | { | |
39 | PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore; | |
40 | BOOL ret = TRUE; | |
41 | PCCTL_CONTEXT toAdd = NULL, existing = NULL; | |
42 | ||
43 | TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCtlContext, dwAddDisposition, | |
44 | ppStoreContext); | |
45 | ||
46 | if (dwAddDisposition != CERT_STORE_ADD_ALWAYS) | |
47 | { | |
48 | existing = CertFindCTLInStore(hCertStore, 0, 0, CTL_FIND_EXISTING, | |
49 | pCtlContext, NULL); | |
50 | } | |
51 | ||
52 | switch (dwAddDisposition) | |
53 | { | |
54 | case CERT_STORE_ADD_ALWAYS: | |
55 | toAdd = CertDuplicateCTLContext(pCtlContext); | |
56 | break; | |
57 | case CERT_STORE_ADD_NEW: | |
58 | if (existing) | |
59 | { | |
60 | TRACE("found matching CTL, not adding\n"); | |
61 | SetLastError(CRYPT_E_EXISTS); | |
62 | ret = FALSE; | |
63 | } | |
64 | else | |
65 | toAdd = CertDuplicateCTLContext(pCtlContext); | |
66 | break; | |
67 | case CERT_STORE_ADD_NEWER: | |
68 | if (existing) | |
69 | { | |
70 | LONG newer = CompareFileTime(&existing->pCtlInfo->ThisUpdate, | |
71 | &pCtlContext->pCtlInfo->ThisUpdate); | |
72 | ||
73 | if (newer < 0) | |
74 | toAdd = CertDuplicateCTLContext(pCtlContext); | |
75 | else | |
76 | { | |
77 | TRACE("existing CTL is newer, not adding\n"); | |
78 | SetLastError(CRYPT_E_EXISTS); | |
79 | ret = FALSE; | |
cefe8820 JL |
80 | } |
81 | } | |
82 | else | |
83 | toAdd = CertDuplicateCTLContext(pCtlContext); | |
84 | break; | |
85 | case CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES: | |
86 | if (existing) | |
87 | { | |
88 | LONG newer = CompareFileTime(&existing->pCtlInfo->ThisUpdate, | |
89 | &pCtlContext->pCtlInfo->ThisUpdate); | |
90 | ||
91 | if (newer < 0) | |
92 | { | |
93 | toAdd = CertDuplicateCTLContext(pCtlContext); | |
94 | CtlContext_CopyProperties(existing, pCtlContext); | |
95 | } | |
96 | else | |
97 | { | |
98 | TRACE("existing CTL is newer, not adding\n"); | |
99 | SetLastError(CRYPT_E_EXISTS); | |
100 | ret = FALSE; | |
07de224b JL |
101 | } |
102 | } | |
103 | else | |
104 | toAdd = CertDuplicateCTLContext(pCtlContext); | |
105 | break; | |
106 | case CERT_STORE_ADD_REPLACE_EXISTING: | |
107 | toAdd = CertDuplicateCTLContext(pCtlContext); | |
108 | break; | |
109 | case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES: | |
110 | toAdd = CertDuplicateCTLContext(pCtlContext); | |
111 | if (existing) | |
112 | CtlContext_CopyProperties(toAdd, existing); | |
113 | break; | |
114 | case CERT_STORE_ADD_USE_EXISTING: | |
115 | if (existing) | |
116 | CtlContext_CopyProperties(existing, pCtlContext); | |
117 | break; | |
118 | default: | |
119 | FIXME("Unimplemented add disposition %d\n", dwAddDisposition); | |
120 | ret = FALSE; | |
121 | } | |
122 | ||
123 | if (toAdd) | |
124 | { | |
125 | if (store) | |
126 | ret = store->ctls.addContext(store, (void *)toAdd, | |
127 | (void *)existing, (const void **)ppStoreContext); | |
128 | else if (ppStoreContext) | |
129 | *ppStoreContext = CertDuplicateCTLContext(toAdd); | |
130 | CertFreeCTLContext(toAdd); | |
131 | } | |
132 | CertFreeCTLContext(existing); | |
133 | ||
134 | TRACE("returning %d\n", ret); | |
135 | return ret; | |
136 | } | |
137 | ||
aebb9372 JL |
138 | BOOL WINAPI CertAddEncodedCTLToStore(HCERTSTORE hCertStore, |
139 | DWORD dwMsgAndCertEncodingType, const BYTE *pbCtlEncoded, DWORD cbCtlEncoded, | |
140 | DWORD dwAddDisposition, PCCTL_CONTEXT *ppCtlContext) | |
141 | { | |
142 | PCCTL_CONTEXT ctl = CertCreateCTLContext(dwMsgAndCertEncodingType, | |
143 | pbCtlEncoded, cbCtlEncoded); | |
144 | BOOL ret; | |
145 | ||
146 | TRACE("(%p, %08x, %p, %d, %08x, %p)\n", hCertStore, | |
147 | dwMsgAndCertEncodingType, pbCtlEncoded, cbCtlEncoded, dwAddDisposition, | |
148 | ppCtlContext); | |
149 | ||
150 | if (ctl) | |
151 | { | |
152 | ret = CertAddCTLContextToStore(hCertStore, ctl, dwAddDisposition, | |
153 | ppCtlContext); | |
154 | CertFreeCTLContext(ctl); | |
155 | } | |
156 | else | |
157 | ret = FALSE; | |
158 | return ret; | |
159 | } | |
160 | ||
7572f61f JL |
161 | PCCTL_CONTEXT WINAPI CertEnumCTLsInStore(HCERTSTORE hCertStore, |
162 | PCCTL_CONTEXT pPrev) | |
163 | { | |
164 | WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore; | |
165 | PCCTL_CONTEXT ret; | |
166 | ||
167 | TRACE("(%p, %p)\n", hCertStore, pPrev); | |
168 | if (!hCertStore) | |
169 | ret = NULL; | |
170 | else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC) | |
171 | ret = NULL; | |
172 | else | |
173 | ret = (PCCTL_CONTEXT)hcs->ctls.enumContext(hcs, (void *)pPrev); | |
174 | return ret; | |
175 | } | |
176 | ||
4f62230e JL |
177 | typedef BOOL (*CtlCompareFunc)(PCCTL_CONTEXT pCtlContext, DWORD dwType, |
178 | DWORD dwFlags, const void *pvPara); | |
179 | ||
180 | static BOOL compare_ctl_any(PCCTL_CONTEXT pCtlContext, DWORD dwType, | |
181 | DWORD dwFlags, const void *pvPara) | |
182 | { | |
183 | return TRUE; | |
184 | } | |
185 | ||
186 | static BOOL compare_ctl_by_md5_hash(PCCTL_CONTEXT pCtlContext, DWORD dwType, | |
187 | DWORD dwFlags, const void *pvPara) | |
188 | { | |
189 | BOOL ret; | |
190 | BYTE hash[16]; | |
191 | DWORD size = sizeof(hash); | |
192 | ||
193 | ret = CertGetCTLContextProperty(pCtlContext, CERT_MD5_HASH_PROP_ID, hash, | |
194 | &size); | |
195 | if (ret) | |
196 | { | |
197 | const CRYPT_HASH_BLOB *pHash = (const CRYPT_HASH_BLOB *)pvPara; | |
198 | ||
199 | if (size == pHash->cbData) | |
200 | ret = !memcmp(pHash->pbData, hash, size); | |
201 | else | |
202 | ret = FALSE; | |
203 | } | |
204 | return ret; | |
205 | } | |
206 | ||
207 | static BOOL compare_ctl_by_sha1_hash(PCCTL_CONTEXT pCtlContext, DWORD dwType, | |
208 | DWORD dwFlags, const void *pvPara) | |
209 | { | |
210 | BOOL ret; | |
211 | BYTE hash[20]; | |
212 | DWORD size = sizeof(hash); | |
213 | ||
214 | ret = CertGetCTLContextProperty(pCtlContext, CERT_SHA1_HASH_PROP_ID, hash, | |
215 | &size); | |
216 | if (ret) | |
217 | { | |
218 | const CRYPT_HASH_BLOB *pHash = (const CRYPT_HASH_BLOB *)pvPara; | |
219 | ||
220 | if (size == pHash->cbData) | |
221 | ret = !memcmp(pHash->pbData, hash, size); | |
222 | else | |
223 | ret = FALSE; | |
224 | } | |
225 | return ret; | |
226 | } | |
227 | ||
228 | static BOOL compare_ctl_existing(PCCTL_CONTEXT pCtlContext, DWORD dwType, | |
229 | DWORD dwFlags, const void *pvPara) | |
230 | { | |
231 | BOOL ret; | |
232 | ||
233 | if (pvPara) | |
234 | { | |
235 | PCCTL_CONTEXT ctl = (PCCTL_CONTEXT)pvPara; | |
236 | ||
237 | if (pCtlContext->cbCtlContext == ctl->cbCtlContext) | |
238 | { | |
239 | if (ctl->cbCtlContext) | |
240 | ret = !memcmp(pCtlContext->pbCtlContext, ctl->pbCtlContext, | |
241 | ctl->cbCtlContext); | |
242 | else | |
243 | ret = TRUE; | |
244 | } | |
245 | else | |
246 | ret = FALSE; | |
247 | } | |
248 | else | |
249 | ret = FALSE; | |
250 | return ret; | |
251 | } | |
252 | ||
253 | PCCTL_CONTEXT WINAPI CertFindCTLInStore(HCERTSTORE hCertStore, | |
254 | DWORD dwCertEncodingType, DWORD dwFindFlags, DWORD dwFindType, | |
255 | const void *pvFindPara, PCCTL_CONTEXT pPrevCtlContext) | |
256 | { | |
257 | PCCTL_CONTEXT ret; | |
258 | CtlCompareFunc compare; | |
259 | ||
260 | TRACE("(%p, %d, %d, %d, %p, %p)\n", hCertStore, dwCertEncodingType, | |
261 | dwFindFlags, dwFindType, pvFindPara, pPrevCtlContext); | |
262 | ||
263 | switch (dwFindType) | |
264 | { | |
265 | case CTL_FIND_ANY: | |
266 | compare = compare_ctl_any; | |
267 | break; | |
268 | case CTL_FIND_SHA1_HASH: | |
269 | compare = compare_ctl_by_sha1_hash; | |
270 | break; | |
271 | case CTL_FIND_MD5_HASH: | |
272 | compare = compare_ctl_by_md5_hash; | |
273 | break; | |
274 | case CTL_FIND_EXISTING: | |
275 | compare = compare_ctl_existing; | |
276 | break; | |
277 | default: | |
278 | FIXME("find type %08x unimplemented\n", dwFindType); | |
279 | compare = NULL; | |
280 | } | |
281 | ||
282 | if (compare) | |
283 | { | |
284 | BOOL matches = FALSE; | |
285 | ||
286 | ret = pPrevCtlContext; | |
287 | do { | |
288 | ret = CertEnumCTLsInStore(hCertStore, ret); | |
289 | if (ret) | |
290 | matches = compare(ret, dwFindType, dwFindFlags, pvFindPara); | |
291 | } while (ret != NULL && !matches); | |
292 | if (!ret) | |
293 | SetLastError(CRYPT_E_NOT_FOUND); | |
294 | } | |
295 | else | |
296 | { | |
297 | SetLastError(CRYPT_E_NOT_FOUND); | |
298 | ret = NULL; | |
299 | } | |
300 | return ret; | |
301 | } | |
302 | ||
7a2cedad JL |
303 | BOOL WINAPI CertDeleteCTLFromStore(PCCTL_CONTEXT pCtlContext) |
304 | { | |
305 | BOOL ret; | |
306 | ||
307 | TRACE("(%p)\n", pCtlContext); | |
308 | ||
309 | if (!pCtlContext) | |
310 | ret = TRUE; | |
311 | else if (!pCtlContext->hCertStore) | |
312 | { | |
313 | ret = TRUE; | |
314 | CertFreeCTLContext(pCtlContext); | |
315 | } | |
316 | else | |
317 | { | |
318 | PWINECRYPT_CERTSTORE hcs = | |
319 | (PWINECRYPT_CERTSTORE)pCtlContext->hCertStore; | |
320 | ||
321 | if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC) | |
322 | ret = FALSE; | |
323 | else | |
324 | ret = hcs->ctls.deleteContext(hcs, (void *)pCtlContext); | |
325 | CertFreeCTLContext(pCtlContext); | |
326 | } | |
327 | return ret; | |
328 | } | |
329 | ||
429b1e1b JL |
330 | PCCTL_CONTEXT WINAPI CertCreateCTLContext(DWORD dwMsgAndCertEncodingType, |
331 | const BYTE *pbCtlEncoded, DWORD cbCtlEncoded) | |
332 | { | |
333 | PCTL_CONTEXT ctl = NULL; | |
334 | HCRYPTMSG msg; | |
335 | BOOL ret; | |
336 | BYTE *content = NULL; | |
337 | DWORD contentSize = 0, size; | |
338 | PCTL_INFO ctlInfo = NULL; | |
339 | ||
340 | TRACE("(%08x, %p, %d)\n", dwMsgAndCertEncodingType, pbCtlEncoded, | |
341 | cbCtlEncoded); | |
342 | ||
343 | if (GET_CERT_ENCODING_TYPE(dwMsgAndCertEncodingType) != X509_ASN_ENCODING) | |
344 | { | |
345 | SetLastError(E_INVALIDARG); | |
346 | return NULL; | |
347 | } | |
348 | if (!pbCtlEncoded || !cbCtlEncoded) | |
349 | { | |
350 | SetLastError(ERROR_INVALID_DATA); | |
351 | return NULL; | |
352 | } | |
353 | msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, 0, | |
354 | 0, NULL, NULL); | |
355 | if (!msg) | |
356 | return NULL; | |
357 | ret = CryptMsgUpdate(msg, pbCtlEncoded, cbCtlEncoded, TRUE); | |
358 | if (!ret) | |
359 | { | |
360 | SetLastError(ERROR_INVALID_DATA); | |
361 | goto end; | |
362 | } | |
363 | /* Check that it's really a CTL */ | |
364 | ret = CryptMsgGetParam(msg, CMSG_INNER_CONTENT_TYPE_PARAM, 0, NULL, &size); | |
365 | if (ret) | |
366 | { | |
367 | char *innerContent = CryptMemAlloc(size); | |
368 | ||
369 | if (innerContent) | |
370 | { | |
371 | ret = CryptMsgGetParam(msg, CMSG_INNER_CONTENT_TYPE_PARAM, 0, | |
372 | innerContent, &size); | |
373 | if (ret) | |
374 | { | |
375 | if (strcmp(innerContent, szOID_CTL)) | |
376 | { | |
377 | SetLastError(ERROR_INVALID_DATA); | |
378 | ret = FALSE; | |
379 | } | |
380 | } | |
381 | CryptMemFree(innerContent); | |
382 | } | |
383 | else | |
384 | { | |
385 | SetLastError(ERROR_OUTOFMEMORY); | |
386 | ret = FALSE; | |
387 | } | |
388 | } | |
389 | if (!ret) | |
390 | goto end; | |
391 | ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &contentSize); | |
392 | if (!ret) | |
393 | goto end; | |
394 | content = CryptMemAlloc(contentSize); | |
395 | if (content) | |
396 | { | |
397 | ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, content, | |
398 | &contentSize); | |
399 | if (ret) | |
400 | { | |
401 | ret = CryptDecodeObjectEx(dwMsgAndCertEncodingType, PKCS_CTL, | |
402 | content, contentSize, CRYPT_DECODE_ALLOC_FLAG, NULL, | |
403 | (BYTE *)&ctlInfo, &size); | |
404 | if (ret) | |
405 | { | |
7589715c | 406 | ctl = Context_CreateDataContext(sizeof(CTL_CONTEXT)); |
429b1e1b JL |
407 | if (ctl) |
408 | { | |
409 | BYTE *data = CryptMemAlloc(cbCtlEncoded); | |
410 | ||
411 | if (data) | |
412 | { | |
413 | memcpy(data, pbCtlEncoded, cbCtlEncoded); | |
414 | ctl->dwMsgAndCertEncodingType = | |
415 | X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; | |
416 | ctl->pbCtlEncoded = data; | |
417 | ctl->cbCtlEncoded = cbCtlEncoded; | |
418 | ctl->pCtlInfo = ctlInfo; | |
419 | ctl->hCertStore = NULL; | |
420 | ctl->hCryptMsg = msg; | |
421 | ctl->pbCtlContext = content; | |
422 | ctl->cbCtlContext = contentSize; | |
423 | } | |
424 | else | |
425 | { | |
426 | SetLastError(ERROR_OUTOFMEMORY); | |
427 | ret = FALSE; | |
428 | } | |
429 | } | |
430 | else | |
431 | { | |
432 | SetLastError(ERROR_OUTOFMEMORY); | |
433 | ret = FALSE; | |
434 | } | |
435 | } | |
436 | } | |
437 | } | |
438 | else | |
439 | { | |
440 | SetLastError(ERROR_OUTOFMEMORY); | |
441 | ret = FALSE; | |
442 | } | |
443 | ||
444 | end: | |
445 | if (!ret) | |
446 | { | |
447 | CryptMemFree(ctl); | |
448 | ctl = NULL; | |
449 | LocalFree(ctlInfo); | |
450 | CryptMemFree(content); | |
451 | CryptMsgClose(msg); | |
452 | } | |
453 | return (PCCTL_CONTEXT)ctl; | |
454 | } | |
455 | ||
3eb62ad6 JL |
456 | PCCTL_CONTEXT WINAPI CertDuplicateCTLContext(PCCTL_CONTEXT pCtlContext) |
457 | { | |
458 | TRACE("(%p)\n", pCtlContext); | |
459 | Context_AddRef((void *)pCtlContext, sizeof(CTL_CONTEXT)); | |
460 | return pCtlContext; | |
461 | } | |
462 | ||
429b1e1b JL |
463 | static void CTLDataContext_Free(void *context) |
464 | { | |
465 | PCTL_CONTEXT ctlContext = (PCTL_CONTEXT)context; | |
466 | ||
467 | CryptMsgClose(ctlContext->hCryptMsg); | |
468 | CryptMemFree(ctlContext->pbCtlEncoded); | |
469 | CryptMemFree(ctlContext->pbCtlContext); | |
470 | LocalFree(ctlContext->pCtlInfo); | |
471 | } | |
472 | ||
473 | BOOL WINAPI CertFreeCTLContext(PCCTL_CONTEXT pCTLContext) | |
474 | { | |
475 | TRACE("(%p)\n", pCTLContext); | |
476 | ||
477 | if (pCTLContext) | |
478 | Context_Release((void *)pCTLContext, sizeof(CTL_CONTEXT), | |
479 | CTLDataContext_Free); | |
480 | return TRUE; | |
481 | } | |
0ada2b93 JL |
482 | |
483 | DWORD WINAPI CertEnumCTLContextProperties(PCCTL_CONTEXT pCTLContext, | |
484 | DWORD dwPropId) | |
485 | { | |
486 | PCONTEXT_PROPERTY_LIST properties = Context_GetProperties( | |
487 | (void *)pCTLContext, sizeof(CTL_CONTEXT)); | |
488 | DWORD ret; | |
489 | ||
490 | TRACE("(%p, %d)\n", pCTLContext, dwPropId); | |
491 | ||
492 | if (properties) | |
493 | ret = ContextPropertyList_EnumPropIDs(properties, dwPropId); | |
494 | else | |
495 | ret = 0; | |
496 | return ret; | |
497 | } | |
498 | ||
499 | static BOOL CTLContext_SetProperty(PCCTL_CONTEXT context, DWORD dwPropId, | |
500 | DWORD dwFlags, const void *pvData); | |
501 | ||
502 | static BOOL CTLContext_GetHashProp(PCCTL_CONTEXT context, DWORD dwPropId, | |
503 | ALG_ID algID, const BYTE *toHash, DWORD toHashLen, void *pvData, | |
504 | DWORD *pcbData) | |
505 | { | |
506 | BOOL ret = CryptHashCertificate(0, algID, 0, toHash, toHashLen, pvData, | |
507 | pcbData); | |
00c50a67 | 508 | if (ret && pvData) |
0ada2b93 JL |
509 | { |
510 | CRYPT_DATA_BLOB blob = { *pcbData, pvData }; | |
511 | ||
512 | ret = CTLContext_SetProperty(context, dwPropId, 0, &blob); | |
513 | } | |
514 | return ret; | |
515 | } | |
516 | ||
517 | static BOOL CTLContext_GetProperty(PCCTL_CONTEXT context, DWORD dwPropId, | |
518 | void *pvData, DWORD *pcbData) | |
519 | { | |
520 | PCONTEXT_PROPERTY_LIST properties = | |
521 | Context_GetProperties(context, sizeof(CTL_CONTEXT)); | |
522 | BOOL ret; | |
523 | CRYPT_DATA_BLOB blob; | |
524 | ||
525 | TRACE("(%p, %d, %p, %p)\n", context, dwPropId, pvData, pcbData); | |
526 | ||
527 | if (properties) | |
528 | ret = ContextPropertyList_FindProperty(properties, dwPropId, &blob); | |
529 | else | |
530 | ret = FALSE; | |
531 | if (ret) | |
532 | { | |
533 | if (!pvData) | |
534 | *pcbData = blob.cbData; | |
535 | else if (*pcbData < blob.cbData) | |
536 | { | |
537 | SetLastError(ERROR_MORE_DATA); | |
538 | *pcbData = blob.cbData; | |
539 | ret = FALSE; | |
540 | } | |
541 | else | |
542 | { | |
543 | memcpy(pvData, blob.pbData, blob.cbData); | |
544 | *pcbData = blob.cbData; | |
545 | } | |
546 | } | |
547 | else | |
548 | { | |
549 | /* Implicit properties */ | |
550 | switch (dwPropId) | |
551 | { | |
552 | case CERT_SHA1_HASH_PROP_ID: | |
553 | ret = CTLContext_GetHashProp(context, dwPropId, CALG_SHA1, | |
554 | context->pbCtlEncoded, context->cbCtlEncoded, pvData, pcbData); | |
555 | break; | |
556 | case CERT_MD5_HASH_PROP_ID: | |
557 | ret = CTLContext_GetHashProp(context, dwPropId, CALG_MD5, | |
558 | context->pbCtlEncoded, context->cbCtlEncoded, pvData, pcbData); | |
559 | break; | |
560 | default: | |
561 | SetLastError(CRYPT_E_NOT_FOUND); | |
562 | } | |
563 | } | |
564 | TRACE("returning %d\n", ret); | |
565 | return ret; | |
566 | } | |
567 | ||
568 | BOOL WINAPI CertGetCTLContextProperty(PCCTL_CONTEXT pCTLContext, | |
569 | DWORD dwPropId, void *pvData, DWORD *pcbData) | |
570 | { | |
571 | BOOL ret; | |
572 | ||
573 | TRACE("(%p, %d, %p, %p)\n", pCTLContext, dwPropId, pvData, pcbData); | |
574 | ||
575 | switch (dwPropId) | |
576 | { | |
577 | case 0: | |
578 | case CERT_CERT_PROP_ID: | |
579 | case CERT_CRL_PROP_ID: | |
580 | case CERT_CTL_PROP_ID: | |
581 | SetLastError(E_INVALIDARG); | |
582 | ret = FALSE; | |
583 | break; | |
584 | case CERT_ACCESS_STATE_PROP_ID: | |
585 | if (!pvData) | |
586 | { | |
587 | *pcbData = sizeof(DWORD); | |
588 | ret = TRUE; | |
589 | } | |
590 | else if (*pcbData < sizeof(DWORD)) | |
591 | { | |
592 | SetLastError(ERROR_MORE_DATA); | |
593 | *pcbData = sizeof(DWORD); | |
594 | ret = FALSE; | |
595 | } | |
596 | else | |
597 | { | |
598 | if (pCTLContext->hCertStore) | |
599 | ret = CertGetStoreProperty(pCTLContext->hCertStore, dwPropId, | |
600 | pvData, pcbData); | |
601 | else | |
602 | *(DWORD *)pvData = 0; | |
603 | ret = TRUE; | |
604 | } | |
605 | break; | |
606 | default: | |
607 | ret = CTLContext_GetProperty(pCTLContext, dwPropId, pvData, | |
608 | pcbData); | |
609 | } | |
610 | return ret; | |
611 | } | |
612 | ||
613 | static BOOL CTLContext_SetProperty(PCCTL_CONTEXT context, DWORD dwPropId, | |
614 | DWORD dwFlags, const void *pvData) | |
615 | { | |
616 | PCONTEXT_PROPERTY_LIST properties = | |
617 | Context_GetProperties(context, sizeof(CTL_CONTEXT)); | |
618 | BOOL ret; | |
619 | ||
620 | TRACE("(%p, %d, %08x, %p)\n", context, dwPropId, dwFlags, pvData); | |
621 | ||
622 | if (!properties) | |
623 | ret = FALSE; | |
624 | else if (!pvData) | |
625 | { | |
626 | ContextPropertyList_RemoveProperty(properties, dwPropId); | |
627 | ret = TRUE; | |
628 | } | |
629 | else | |
630 | { | |
631 | switch (dwPropId) | |
632 | { | |
633 | case CERT_AUTO_ENROLL_PROP_ID: | |
634 | case CERT_CTL_USAGE_PROP_ID: /* same as CERT_ENHKEY_USAGE_PROP_ID */ | |
635 | case CERT_DESCRIPTION_PROP_ID: | |
636 | case CERT_FRIENDLY_NAME_PROP_ID: | |
637 | case CERT_HASH_PROP_ID: | |
638 | case CERT_KEY_IDENTIFIER_PROP_ID: | |
639 | case CERT_MD5_HASH_PROP_ID: | |
640 | case CERT_NEXT_UPDATE_LOCATION_PROP_ID: | |
641 | case CERT_PUBKEY_ALG_PARA_PROP_ID: | |
642 | case CERT_PVK_FILE_PROP_ID: | |
643 | case CERT_SIGNATURE_HASH_PROP_ID: | |
644 | case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID: | |
645 | case CERT_SUBJECT_NAME_MD5_HASH_PROP_ID: | |
646 | case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID: | |
647 | case CERT_ENROLLMENT_PROP_ID: | |
648 | case CERT_CROSS_CERT_DIST_POINTS_PROP_ID: | |
649 | case CERT_RENEWAL_PROP_ID: | |
650 | { | |
651 | PCRYPT_DATA_BLOB blob = (PCRYPT_DATA_BLOB)pvData; | |
652 | ||
653 | ret = ContextPropertyList_SetProperty(properties, dwPropId, | |
654 | blob->pbData, blob->cbData); | |
655 | break; | |
656 | } | |
657 | case CERT_DATE_STAMP_PROP_ID: | |
658 | ret = ContextPropertyList_SetProperty(properties, dwPropId, | |
659 | (const BYTE *)pvData, sizeof(FILETIME)); | |
660 | break; | |
661 | default: | |
662 | FIXME("%d: stub\n", dwPropId); | |
663 | ret = FALSE; | |
664 | } | |
665 | } | |
666 | TRACE("returning %d\n", ret); | |
667 | return ret; | |
668 | } | |
669 | ||
670 | BOOL WINAPI CertSetCTLContextProperty(PCCTL_CONTEXT pCTLContext, | |
671 | DWORD dwPropId, DWORD dwFlags, const void *pvData) | |
672 | { | |
673 | BOOL ret; | |
674 | ||
675 | TRACE("(%p, %d, %08x, %p)\n", pCTLContext, dwPropId, dwFlags, pvData); | |
676 | ||
677 | /* Handle special cases for "read-only"/invalid prop IDs. Windows just | |
678 | * crashes on most of these, I'll be safer. | |
679 | */ | |
680 | switch (dwPropId) | |
681 | { | |
682 | case 0: | |
683 | case CERT_ACCESS_STATE_PROP_ID: | |
684 | case CERT_CERT_PROP_ID: | |
685 | case CERT_CRL_PROP_ID: | |
686 | case CERT_CTL_PROP_ID: | |
687 | SetLastError(E_INVALIDARG); | |
688 | return FALSE; | |
689 | } | |
690 | ret = CTLContext_SetProperty(pCTLContext, dwPropId, dwFlags, pvData); | |
691 | TRACE("returning %d\n", ret); | |
692 | return ret; | |
693 | } |