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