Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenserialize.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2004-2007 Juan Lang 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00017 */ 00018 00019 #include "config.h" 00020 #include "wine/port.h" 00021 00022 #include <stdarg.h> 00023 #include "windef.h" 00024 #include "winbase.h" 00025 #include "wincrypt.h" 00026 #include "wine/debug.h" 00027 #include "wine/exception.h" 00028 #include "crypt32_private.h" 00029 00030 WINE_DEFAULT_DEBUG_CHANNEL(crypt); 00031 00032 /* An extended certificate property in serialized form is prefixed by this 00033 * header. 00034 */ 00035 typedef struct _WINE_CERT_PROP_HEADER 00036 { 00037 DWORD propID; 00038 DWORD unknown; /* always 1 */ 00039 DWORD cb; 00040 } WINE_CERT_PROP_HEADER, *PWINE_CERT_PROP_HEADER; 00041 00042 static BOOL CRYPT_SerializeStoreElement(const void *context, 00043 const BYTE *encodedContext, DWORD cbEncodedContext, DWORD contextPropID, 00044 PCWINE_CONTEXT_INTERFACE contextInterface, DWORD dwFlags, BOOL omitHashes, 00045 BYTE *pbElement, DWORD *pcbElement) 00046 { 00047 BOOL ret; 00048 00049 TRACE("(%p, %p, %08x, %d, %p, %p)\n", context, contextInterface, dwFlags, 00050 omitHashes, pbElement, pcbElement); 00051 00052 if (context) 00053 { 00054 DWORD bytesNeeded = sizeof(WINE_CERT_PROP_HEADER) + cbEncodedContext; 00055 DWORD prop = 0; 00056 00057 ret = TRUE; 00058 do { 00059 prop = contextInterface->enumProps(context, prop); 00060 if (prop && (!omitHashes || !IS_CERT_HASH_PROP_ID(prop))) 00061 { 00062 DWORD propSize = 0; 00063 00064 ret = contextInterface->getProp(context, prop, NULL, &propSize); 00065 if (ret) 00066 bytesNeeded += sizeof(WINE_CERT_PROP_HEADER) + propSize; 00067 } 00068 } while (ret && prop != 0); 00069 00070 if (!pbElement) 00071 { 00072 *pcbElement = bytesNeeded; 00073 ret = TRUE; 00074 } 00075 else if (*pcbElement < bytesNeeded) 00076 { 00077 *pcbElement = bytesNeeded; 00078 SetLastError(ERROR_MORE_DATA); 00079 ret = FALSE; 00080 } 00081 else 00082 { 00083 PWINE_CERT_PROP_HEADER hdr; 00084 DWORD bufSize = 0; 00085 LPBYTE buf = NULL; 00086 00087 prop = 0; 00088 do { 00089 prop = contextInterface->enumProps(context, prop); 00090 if (prop && (!omitHashes || !IS_CERT_HASH_PROP_ID(prop))) 00091 { 00092 DWORD propSize = 0; 00093 00094 ret = contextInterface->getProp(context, prop, NULL, 00095 &propSize); 00096 if (ret) 00097 { 00098 if (bufSize < propSize) 00099 { 00100 if (buf) 00101 buf = CryptMemRealloc(buf, propSize); 00102 else 00103 buf = CryptMemAlloc(propSize); 00104 bufSize = propSize; 00105 } 00106 if (buf) 00107 { 00108 ret = contextInterface->getProp(context, prop, buf, 00109 &propSize); 00110 if (ret) 00111 { 00112 hdr = (PWINE_CERT_PROP_HEADER)pbElement; 00113 hdr->propID = prop; 00114 hdr->unknown = 1; 00115 hdr->cb = propSize; 00116 pbElement += sizeof(WINE_CERT_PROP_HEADER); 00117 if (propSize) 00118 { 00119 memcpy(pbElement, buf, propSize); 00120 pbElement += propSize; 00121 } 00122 } 00123 } 00124 else 00125 ret = FALSE; 00126 } 00127 } 00128 } while (ret && prop != 0); 00129 CryptMemFree(buf); 00130 00131 hdr = (PWINE_CERT_PROP_HEADER)pbElement; 00132 hdr->propID = contextPropID; 00133 hdr->unknown = 1; 00134 hdr->cb = cbEncodedContext; 00135 memcpy(pbElement + sizeof(WINE_CERT_PROP_HEADER), 00136 encodedContext, cbEncodedContext); 00137 } 00138 } 00139 else 00140 ret = FALSE; 00141 return ret; 00142 } 00143 00144 BOOL WINAPI CertSerializeCertificateStoreElement(PCCERT_CONTEXT pCertContext, 00145 DWORD dwFlags, BYTE *pbElement, DWORD *pcbElement) 00146 { 00147 return CRYPT_SerializeStoreElement(pCertContext, 00148 pCertContext->pbCertEncoded, pCertContext->cbCertEncoded, 00149 CERT_CERT_PROP_ID, pCertInterface, dwFlags, FALSE, pbElement, pcbElement); 00150 } 00151 00152 BOOL WINAPI CertSerializeCRLStoreElement(PCCRL_CONTEXT pCrlContext, 00153 DWORD dwFlags, BYTE *pbElement, DWORD *pcbElement) 00154 { 00155 return CRYPT_SerializeStoreElement(pCrlContext, 00156 pCrlContext->pbCrlEncoded, pCrlContext->cbCrlEncoded, 00157 CERT_CRL_PROP_ID, pCRLInterface, dwFlags, FALSE, pbElement, pcbElement); 00158 } 00159 00160 BOOL WINAPI CertSerializeCTLStoreElement(PCCTL_CONTEXT pCtlContext, 00161 DWORD dwFlags, BYTE *pbElement, DWORD *pcbElement) 00162 { 00163 return CRYPT_SerializeStoreElement(pCtlContext, 00164 pCtlContext->pbCtlEncoded, pCtlContext->cbCtlEncoded, 00165 CERT_CTL_PROP_ID, pCTLInterface, dwFlags, FALSE, pbElement, pcbElement); 00166 } 00167 00168 /* Looks for the property with ID propID in the buffer buf. Returns a pointer 00169 * to its header if a valid header is found, NULL if not. Valid means the 00170 * length of the property won't overrun buf, and the unknown field is 1. 00171 */ 00172 static const WINE_CERT_PROP_HEADER *CRYPT_findPropID(const BYTE *buf, 00173 DWORD size, DWORD propID) 00174 { 00175 const WINE_CERT_PROP_HEADER *ret = NULL; 00176 BOOL done = FALSE; 00177 00178 while (size && !ret && !done) 00179 { 00180 if (size < sizeof(WINE_CERT_PROP_HEADER)) 00181 { 00182 SetLastError(CRYPT_E_FILE_ERROR); 00183 done = TRUE; 00184 } 00185 else 00186 { 00187 const WINE_CERT_PROP_HEADER *hdr = 00188 (const WINE_CERT_PROP_HEADER *)buf; 00189 00190 size -= sizeof(WINE_CERT_PROP_HEADER); 00191 buf += sizeof(WINE_CERT_PROP_HEADER); 00192 if (size < hdr->cb) 00193 { 00194 SetLastError(E_INVALIDARG); 00195 done = TRUE; 00196 } 00197 else if (!hdr->propID) 00198 { 00199 /* assume a zero prop ID means the data are uninitialized, so 00200 * stop looking. 00201 */ 00202 done = TRUE; 00203 } 00204 else if (hdr->unknown != 1) 00205 { 00206 SetLastError(ERROR_FILE_NOT_FOUND); 00207 done = TRUE; 00208 } 00209 else if (hdr->propID == propID) 00210 ret = hdr; 00211 else 00212 { 00213 buf += hdr->cb; 00214 size -= hdr->cb; 00215 } 00216 } 00217 } 00218 return ret; 00219 } 00220 00221 static BOOL CRYPT_ReadContextProp( 00222 const WINE_CONTEXT_INTERFACE *contextInterface, const void *context, 00223 const WINE_CERT_PROP_HEADER *hdr, const BYTE *pbElement, DWORD cbElement) 00224 { 00225 BOOL ret; 00226 00227 if (cbElement < hdr->cb) 00228 { 00229 SetLastError(E_INVALIDARG); 00230 ret = FALSE; 00231 } 00232 else if (hdr->unknown != 1) 00233 { 00234 SetLastError(ERROR_FILE_NOT_FOUND); 00235 ret = FALSE; 00236 } 00237 else if (hdr->propID != CERT_CERT_PROP_ID && 00238 hdr->propID != CERT_CRL_PROP_ID && hdr->propID != CERT_CTL_PROP_ID) 00239 { 00240 /* Have to create a blob for most types, but not 00241 * for all.. arghh. 00242 */ 00243 switch (hdr->propID) 00244 { 00245 case CERT_AUTO_ENROLL_PROP_ID: 00246 case CERT_CTL_USAGE_PROP_ID: 00247 case CERT_DESCRIPTION_PROP_ID: 00248 case CERT_FRIENDLY_NAME_PROP_ID: 00249 case CERT_HASH_PROP_ID: 00250 case CERT_KEY_IDENTIFIER_PROP_ID: 00251 case CERT_MD5_HASH_PROP_ID: 00252 case CERT_NEXT_UPDATE_LOCATION_PROP_ID: 00253 case CERT_PUBKEY_ALG_PARA_PROP_ID: 00254 case CERT_PVK_FILE_PROP_ID: 00255 case CERT_SIGNATURE_HASH_PROP_ID: 00256 case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID: 00257 case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID: 00258 case CERT_ENROLLMENT_PROP_ID: 00259 case CERT_CROSS_CERT_DIST_POINTS_PROP_ID: 00260 case CERT_RENEWAL_PROP_ID: 00261 { 00262 CRYPT_DATA_BLOB blob = { hdr->cb, 00263 (LPBYTE)pbElement }; 00264 00265 ret = contextInterface->setProp(context, 00266 hdr->propID, 0, &blob); 00267 break; 00268 } 00269 case CERT_DATE_STAMP_PROP_ID: 00270 ret = contextInterface->setProp(context, 00271 hdr->propID, 0, pbElement); 00272 break; 00273 case CERT_KEY_PROV_INFO_PROP_ID: 00274 { 00275 PCRYPT_KEY_PROV_INFO info = 00276 (PCRYPT_KEY_PROV_INFO)pbElement; 00277 00278 CRYPT_FixKeyProvInfoPointers(info); 00279 ret = contextInterface->setProp(context, 00280 hdr->propID, 0, pbElement); 00281 break; 00282 } 00283 default: 00284 ret = FALSE; 00285 } 00286 } 00287 else 00288 { 00289 /* ignore the context itself */ 00290 ret = TRUE; 00291 } 00292 return ret; 00293 } 00294 00295 const void *CRYPT_ReadSerializedElement(const BYTE *pbElement, DWORD cbElement, 00296 DWORD dwContextTypeFlags, DWORD *pdwContentType) 00297 { 00298 const void *context; 00299 00300 TRACE("(%p, %d, %08x, %p)\n", pbElement, cbElement, dwContextTypeFlags, 00301 pdwContentType); 00302 00303 if (!cbElement) 00304 { 00305 SetLastError(ERROR_END_OF_MEDIA); 00306 return NULL; 00307 } 00308 00309 __TRY 00310 { 00311 const WINE_CONTEXT_INTERFACE *contextInterface = NULL; 00312 const WINE_CERT_PROP_HEADER *hdr = NULL; 00313 DWORD type = 0; 00314 BOOL ret; 00315 00316 ret = TRUE; 00317 context = NULL; 00318 if (dwContextTypeFlags == CERT_STORE_ALL_CONTEXT_FLAG) 00319 { 00320 hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CERT_PROP_ID); 00321 if (hdr) 00322 type = CERT_STORE_CERTIFICATE_CONTEXT; 00323 else 00324 { 00325 hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CRL_PROP_ID); 00326 if (hdr) 00327 type = CERT_STORE_CRL_CONTEXT; 00328 else 00329 { 00330 hdr = CRYPT_findPropID(pbElement, cbElement, 00331 CERT_CTL_PROP_ID); 00332 if (hdr) 00333 type = CERT_STORE_CTL_CONTEXT; 00334 } 00335 } 00336 } 00337 else if (dwContextTypeFlags & CERT_STORE_CERTIFICATE_CONTEXT_FLAG) 00338 { 00339 hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CERT_PROP_ID); 00340 type = CERT_STORE_CERTIFICATE_CONTEXT; 00341 } 00342 else if (dwContextTypeFlags & CERT_STORE_CRL_CONTEXT_FLAG) 00343 { 00344 hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CRL_PROP_ID); 00345 type = CERT_STORE_CRL_CONTEXT; 00346 } 00347 else if (dwContextTypeFlags & CERT_STORE_CTL_CONTEXT_FLAG) 00348 { 00349 hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CTL_PROP_ID); 00350 type = CERT_STORE_CTL_CONTEXT; 00351 } 00352 00353 switch (type) 00354 { 00355 case CERT_STORE_CERTIFICATE_CONTEXT: 00356 contextInterface = pCertInterface; 00357 break; 00358 case CERT_STORE_CRL_CONTEXT: 00359 contextInterface = pCRLInterface; 00360 break; 00361 case CERT_STORE_CTL_CONTEXT: 00362 contextInterface = pCTLInterface; 00363 break; 00364 default: 00365 SetLastError(E_INVALIDARG); 00366 ret = FALSE; 00367 } 00368 if (!hdr) 00369 ret = FALSE; 00370 00371 if (ret) 00372 context = contextInterface->create(X509_ASN_ENCODING, 00373 (BYTE *)hdr + sizeof(WINE_CERT_PROP_HEADER), hdr->cb); 00374 if (ret && context) 00375 { 00376 BOOL noMoreProps = FALSE; 00377 00378 while (!noMoreProps && ret) 00379 { 00380 if (cbElement < sizeof(WINE_CERT_PROP_HEADER)) 00381 ret = FALSE; 00382 else 00383 { 00384 const WINE_CERT_PROP_HEADER *hdr = 00385 (const WINE_CERT_PROP_HEADER *)pbElement; 00386 00387 TRACE("prop is %d\n", hdr->propID); 00388 cbElement -= sizeof(WINE_CERT_PROP_HEADER); 00389 pbElement += sizeof(WINE_CERT_PROP_HEADER); 00390 if (!hdr->propID) 00391 { 00392 /* Like in CRYPT_findPropID, stop if the propID is zero 00393 */ 00394 noMoreProps = TRUE; 00395 } 00396 else 00397 ret = CRYPT_ReadContextProp(contextInterface, context, 00398 hdr, pbElement, cbElement); 00399 pbElement += hdr->cb; 00400 cbElement -= hdr->cb; 00401 if (!cbElement) 00402 noMoreProps = TRUE; 00403 } 00404 } 00405 if (ret) 00406 { 00407 if (pdwContentType) 00408 *pdwContentType = type; 00409 } 00410 else 00411 { 00412 contextInterface->free(context); 00413 context = NULL; 00414 } 00415 } 00416 } 00417 __EXCEPT_PAGE_FAULT 00418 { 00419 SetLastError(STATUS_ACCESS_VIOLATION); 00420 context = NULL; 00421 } 00422 __ENDTRY 00423 return context; 00424 } 00425 00426 static const BYTE fileHeader[] = { 0, 0, 0, 0, 'C','E','R','T' }; 00427 00428 typedef BOOL (*read_serialized_func)(void *handle, void *buffer, 00429 DWORD bytesToRead, DWORD *bytesRead); 00430 00431 static BOOL CRYPT_ReadSerializedStore(void *handle, 00432 read_serialized_func read_func, HCERTSTORE store) 00433 { 00434 BYTE fileHeaderBuf[sizeof(fileHeader)]; 00435 DWORD read; 00436 BOOL ret; 00437 00438 /* Failure reading is non-critical, we'll leave the store empty */ 00439 ret = read_func(handle, fileHeaderBuf, sizeof(fileHeaderBuf), &read); 00440 if (ret) 00441 { 00442 if (!read) 00443 ; /* an empty file is okay */ 00444 else if (read != sizeof(fileHeaderBuf)) 00445 ret = FALSE; 00446 else if (!memcmp(fileHeaderBuf, fileHeader, read)) 00447 { 00448 WINE_CERT_PROP_HEADER propHdr; 00449 const void *context = NULL; 00450 const WINE_CONTEXT_INTERFACE *contextInterface = NULL; 00451 LPBYTE buf = NULL; 00452 DWORD bufSize = 0; 00453 00454 do { 00455 ret = read_func(handle, &propHdr, sizeof(propHdr), &read); 00456 if (ret && read == sizeof(propHdr)) 00457 { 00458 if (contextInterface && context && 00459 (propHdr.propID == CERT_CERT_PROP_ID || 00460 propHdr.propID == CERT_CRL_PROP_ID || 00461 propHdr.propID == CERT_CTL_PROP_ID)) 00462 { 00463 /* We have a new context, so free the existing one */ 00464 contextInterface->free(context); 00465 } 00466 if (propHdr.cb > bufSize) 00467 { 00468 /* Not reusing realloc, because the old data aren't 00469 * needed any longer. 00470 */ 00471 CryptMemFree(buf); 00472 buf = CryptMemAlloc(propHdr.cb); 00473 bufSize = propHdr.cb; 00474 } 00475 if (!propHdr.cb) 00476 ; /* Property is empty, nothing to do */ 00477 else if (buf) 00478 { 00479 ret = read_func(handle, buf, propHdr.cb, &read); 00480 if (ret && read == propHdr.cb) 00481 { 00482 if (propHdr.propID == CERT_CERT_PROP_ID) 00483 { 00484 contextInterface = pCertInterface; 00485 ret = contextInterface->addEncodedToStore(store, 00486 X509_ASN_ENCODING, buf, read, 00487 CERT_STORE_ADD_NEW, &context); 00488 } 00489 else if (propHdr.propID == CERT_CRL_PROP_ID) 00490 { 00491 contextInterface = pCRLInterface; 00492 ret = contextInterface->addEncodedToStore(store, 00493 X509_ASN_ENCODING, buf, read, 00494 CERT_STORE_ADD_NEW, &context); 00495 } 00496 else if (propHdr.propID == CERT_CTL_PROP_ID) 00497 { 00498 contextInterface = pCTLInterface; 00499 ret = contextInterface->addEncodedToStore(store, 00500 X509_ASN_ENCODING, buf, read, 00501 CERT_STORE_ADD_NEW, &context); 00502 } 00503 else 00504 { 00505 if (!contextInterface) 00506 { 00507 WARN("prop id %d before a context id\n", 00508 propHdr.propID); 00509 ret = FALSE; 00510 } 00511 else 00512 ret = CRYPT_ReadContextProp( 00513 contextInterface, context, &propHdr, buf, 00514 read); 00515 } 00516 } 00517 } 00518 else 00519 ret = FALSE; 00520 } 00521 } while (ret && read > 0 && propHdr.cb); 00522 if (contextInterface && context) 00523 { 00524 /* Free the last context added */ 00525 contextInterface->free(context); 00526 } 00527 CryptMemFree(buf); 00528 ret = TRUE; 00529 } 00530 else 00531 ret = FALSE; 00532 } 00533 else 00534 ret = TRUE; 00535 return ret; 00536 } 00537 00538 static BOOL read_file_wrapper(void *handle, void *buffer, DWORD bytesToRead, 00539 DWORD *bytesRead) 00540 { 00541 return ReadFile(handle, buffer, bytesToRead, bytesRead, NULL); 00542 } 00543 00544 BOOL CRYPT_ReadSerializedStoreFromFile(HANDLE file, HCERTSTORE store) 00545 { 00546 return CRYPT_ReadSerializedStore(file, read_file_wrapper, store); 00547 } 00548 00549 struct BlobReader 00550 { 00551 const CRYPT_DATA_BLOB *blob; 00552 DWORD current; 00553 }; 00554 00555 static BOOL read_blob_wrapper(void *handle, void *buffer, DWORD bytesToRead, 00556 DWORD *bytesRead) 00557 { 00558 struct BlobReader *reader = handle; 00559 BOOL ret; 00560 00561 if (reader->current < reader->blob->cbData) 00562 { 00563 *bytesRead = min(bytesToRead, reader->blob->cbData - reader->current); 00564 memcpy(buffer, reader->blob->pbData + reader->current, *bytesRead); 00565 reader->current += *bytesRead; 00566 ret = TRUE; 00567 } 00568 else if (reader->current == reader->blob->cbData) 00569 { 00570 *bytesRead = 0; 00571 ret = TRUE; 00572 } 00573 else 00574 ret = FALSE; 00575 return ret; 00576 } 00577 00578 BOOL CRYPT_ReadSerializedStoreFromBlob(const CRYPT_DATA_BLOB *blob, 00579 HCERTSTORE store) 00580 { 00581 struct BlobReader reader = { blob, 0 }; 00582 00583 return CRYPT_ReadSerializedStore(&reader, read_blob_wrapper, store); 00584 } 00585 00586 static BOOL WINAPI CRYPT_SerializeCertNoHash(PCCERT_CONTEXT pCertContext, 00587 DWORD dwFlags, BYTE *pbElement, DWORD *pcbElement) 00588 { 00589 return CRYPT_SerializeStoreElement(pCertContext, 00590 pCertContext->pbCertEncoded, pCertContext->cbCertEncoded, 00591 CERT_CERT_PROP_ID, pCertInterface, dwFlags, TRUE, pbElement, pcbElement); 00592 } 00593 00594 static BOOL WINAPI CRYPT_SerializeCRLNoHash(PCCRL_CONTEXT pCrlContext, 00595 DWORD dwFlags, BYTE *pbElement, DWORD *pcbElement) 00596 { 00597 return CRYPT_SerializeStoreElement(pCrlContext, 00598 pCrlContext->pbCrlEncoded, pCrlContext->cbCrlEncoded, 00599 CERT_CRL_PROP_ID, pCRLInterface, dwFlags, TRUE, pbElement, pcbElement); 00600 } 00601 00602 static BOOL WINAPI CRYPT_SerializeCTLNoHash(PCCTL_CONTEXT pCtlContext, 00603 DWORD dwFlags, BYTE *pbElement, DWORD *pcbElement) 00604 { 00605 return CRYPT_SerializeStoreElement(pCtlContext, 00606 pCtlContext->pbCtlEncoded, pCtlContext->cbCtlEncoded, 00607 CERT_CTL_PROP_ID, pCTLInterface, dwFlags, TRUE, pbElement, pcbElement); 00608 } 00609 00610 typedef BOOL (*SerializedOutputFunc)(void *handle, const void *buffer, 00611 DWORD size); 00612 00613 static BOOL CRYPT_SerializeContextsToStream(SerializedOutputFunc output, 00614 void *handle, const WINE_CONTEXT_INTERFACE *contextInterface, HCERTSTORE store) 00615 { 00616 const void *context = NULL; 00617 BOOL ret; 00618 00619 do { 00620 context = contextInterface->enumContextsInStore(store, context); 00621 if (context) 00622 { 00623 DWORD size = 0; 00624 LPBYTE buf = NULL; 00625 00626 ret = contextInterface->serialize(context, 0, NULL, &size); 00627 if (size) 00628 buf = CryptMemAlloc(size); 00629 if (buf) 00630 { 00631 ret = contextInterface->serialize(context, 0, buf, &size); 00632 if (ret) 00633 ret = output(handle, buf, size); 00634 } 00635 CryptMemFree(buf); 00636 } 00637 else 00638 ret = TRUE; 00639 } while (ret && context != NULL); 00640 if (context) 00641 contextInterface->free(context); 00642 return ret; 00643 } 00644 00645 static BOOL CRYPT_WriteSerializedStoreToStream(HCERTSTORE store, 00646 SerializedOutputFunc output, void *handle) 00647 { 00648 static const BYTE fileTrailer[12] = { 0 }; 00649 WINE_CONTEXT_INTERFACE interface; 00650 BOOL ret; 00651 00652 ret = output(handle, fileHeader, sizeof(fileHeader)); 00653 if (ret) 00654 { 00655 memcpy(&interface, pCertInterface, sizeof(interface)); 00656 interface.serialize = (SerializeElementFunc)CRYPT_SerializeCertNoHash; 00657 ret = CRYPT_SerializeContextsToStream(output, handle, &interface, 00658 store); 00659 } 00660 if (ret) 00661 { 00662 memcpy(&interface, pCRLInterface, sizeof(interface)); 00663 interface.serialize = (SerializeElementFunc)CRYPT_SerializeCRLNoHash; 00664 ret = CRYPT_SerializeContextsToStream(output, handle, &interface, 00665 store); 00666 } 00667 if (ret) 00668 { 00669 memcpy(&interface, pCTLInterface, sizeof(interface)); 00670 interface.serialize = (SerializeElementFunc)CRYPT_SerializeCTLNoHash; 00671 ret = CRYPT_SerializeContextsToStream(output, handle, &interface, 00672 store); 00673 } 00674 if (ret) 00675 ret = output(handle, fileTrailer, sizeof(fileTrailer)); 00676 return ret; 00677 } 00678 00679 static BOOL CRYPT_FileOutputFunc(void *handle, const void *buffer, DWORD size) 00680 { 00681 return WriteFile(handle, buffer, size, &size, NULL); 00682 } 00683 00684 static BOOL CRYPT_WriteSerializedStoreToFile(HANDLE file, HCERTSTORE store) 00685 { 00686 SetFilePointer(file, 0, NULL, FILE_BEGIN); 00687 return CRYPT_WriteSerializedStoreToStream(store, CRYPT_FileOutputFunc, 00688 file); 00689 } 00690 00691 static BOOL CRYPT_SavePKCSToMem(HCERTSTORE store, 00692 DWORD dwMsgAndCertEncodingType, void *handle) 00693 { 00694 CERT_BLOB *blob = handle; 00695 CRYPT_SIGNED_INFO signedInfo = { 0 }; 00696 PCCERT_CONTEXT cert = NULL; 00697 PCCRL_CONTEXT crl = NULL; 00698 DWORD size; 00699 BOOL ret = TRUE; 00700 00701 TRACE("(%d, %p)\n", blob->pbData ? blob->cbData : 0, blob->pbData); 00702 00703 do { 00704 cert = CertEnumCertificatesInStore(store, cert); 00705 if (cert) 00706 signedInfo.cCertEncoded++; 00707 } while (cert); 00708 if (signedInfo.cCertEncoded) 00709 { 00710 signedInfo.rgCertEncoded = CryptMemAlloc( 00711 signedInfo.cCertEncoded * sizeof(CERT_BLOB)); 00712 if (!signedInfo.rgCertEncoded) 00713 { 00714 SetLastError(ERROR_OUTOFMEMORY); 00715 ret = FALSE; 00716 } 00717 else 00718 { 00719 DWORD i = 0; 00720 00721 do { 00722 cert = CertEnumCertificatesInStore(store, cert); 00723 if (cert) 00724 { 00725 signedInfo.rgCertEncoded[i].cbData = cert->cbCertEncoded; 00726 signedInfo.rgCertEncoded[i].pbData = cert->pbCertEncoded; 00727 i++; 00728 } 00729 } while (cert); 00730 } 00731 } 00732 00733 do { 00734 crl = CertEnumCRLsInStore(store, crl); 00735 if (crl) 00736 signedInfo.cCrlEncoded++; 00737 } while (crl); 00738 if (signedInfo.cCrlEncoded) 00739 { 00740 signedInfo.rgCrlEncoded = CryptMemAlloc( 00741 signedInfo.cCrlEncoded * sizeof(CERT_BLOB)); 00742 if (!signedInfo.rgCrlEncoded) 00743 { 00744 SetLastError(ERROR_OUTOFMEMORY); 00745 ret = FALSE; 00746 } 00747 else 00748 { 00749 DWORD i = 0; 00750 00751 do { 00752 crl = CertEnumCRLsInStore(store, crl); 00753 if (crl) 00754 { 00755 signedInfo.rgCrlEncoded[i].cbData = crl->cbCrlEncoded; 00756 signedInfo.rgCrlEncoded[i].pbData = crl->pbCrlEncoded; 00757 i++; 00758 } 00759 } while (crl); 00760 } 00761 } 00762 if (ret) 00763 { 00764 ret = CRYPT_AsnEncodeCMSSignedInfo(&signedInfo, NULL, &size); 00765 if (ret) 00766 { 00767 if (!blob->pbData) 00768 blob->cbData = size; 00769 else if (blob->cbData < size) 00770 { 00771 blob->cbData = size; 00772 SetLastError(ERROR_MORE_DATA); 00773 ret = FALSE; 00774 } 00775 else 00776 { 00777 blob->cbData = size; 00778 ret = CRYPT_AsnEncodeCMSSignedInfo(&signedInfo, blob->pbData, 00779 &blob->cbData); 00780 } 00781 } 00782 } 00783 CryptMemFree(signedInfo.rgCertEncoded); 00784 CryptMemFree(signedInfo.rgCrlEncoded); 00785 TRACE("returning %d\n", ret); 00786 return ret; 00787 } 00788 00789 static BOOL CRYPT_SavePKCSToFile(HCERTSTORE store, 00790 DWORD dwMsgAndCertEncodingType, void *handle) 00791 { 00792 CERT_BLOB blob = { 0, NULL }; 00793 BOOL ret; 00794 00795 TRACE("(%p)\n", handle); 00796 00797 ret = CRYPT_SavePKCSToMem(store, dwMsgAndCertEncodingType, &blob); 00798 if (ret) 00799 { 00800 blob.pbData = CryptMemAlloc(blob.cbData); 00801 if (blob.pbData) 00802 { 00803 ret = CRYPT_SavePKCSToMem(store, dwMsgAndCertEncodingType, &blob); 00804 if (ret) 00805 ret = WriteFile(handle, blob.pbData, blob.cbData, 00806 &blob.cbData, NULL); 00807 } 00808 else 00809 { 00810 SetLastError(ERROR_OUTOFMEMORY); 00811 ret = FALSE; 00812 } 00813 } 00814 TRACE("returning %d\n", ret); 00815 return ret; 00816 } 00817 00818 static BOOL CRYPT_SaveSerializedToFile(HCERTSTORE store, 00819 DWORD dwMsgAndCertEncodingType, void *handle) 00820 { 00821 return CRYPT_WriteSerializedStoreToFile(handle, store); 00822 } 00823 00824 struct MemWrittenTracker 00825 { 00826 DWORD cbData; 00827 BYTE *pbData; 00828 DWORD written; 00829 }; 00830 00831 /* handle is a pointer to a MemWrittenTracker. Assumes its pointer is valid. */ 00832 static BOOL CRYPT_MemOutputFunc(void *handle, const void *buffer, DWORD size) 00833 { 00834 struct MemWrittenTracker *tracker = handle; 00835 BOOL ret; 00836 00837 if (tracker->written + size > tracker->cbData) 00838 { 00839 SetLastError(ERROR_MORE_DATA); 00840 /* Update written so caller can notify its caller of the required size 00841 */ 00842 tracker->written += size; 00843 ret = FALSE; 00844 } 00845 else 00846 { 00847 memcpy(tracker->pbData + tracker->written, buffer, size); 00848 tracker->written += size; 00849 ret = TRUE; 00850 } 00851 return ret; 00852 } 00853 00854 static BOOL CRYPT_CountSerializedBytes(void *handle, const void *buffer, 00855 DWORD size) 00856 { 00857 *(DWORD *)handle += size; 00858 return TRUE; 00859 } 00860 00861 static BOOL CRYPT_SaveSerializedToMem(HCERTSTORE store, 00862 DWORD dwMsgAndCertEncodingType, void *handle) 00863 { 00864 CERT_BLOB *blob = handle; 00865 DWORD size = 0; 00866 BOOL ret; 00867 00868 ret = CRYPT_WriteSerializedStoreToStream(store, CRYPT_CountSerializedBytes, 00869 &size); 00870 if (ret) 00871 { 00872 if (!blob->pbData) 00873 blob->cbData = size; 00874 else if (blob->cbData < size) 00875 { 00876 SetLastError(ERROR_MORE_DATA); 00877 blob->cbData = size; 00878 ret = FALSE; 00879 } 00880 else 00881 { 00882 struct MemWrittenTracker tracker = { blob->cbData, blob->pbData, 00883 0 }; 00884 00885 ret = CRYPT_WriteSerializedStoreToStream(store, CRYPT_MemOutputFunc, 00886 &tracker); 00887 if (!ret && GetLastError() == ERROR_MORE_DATA) 00888 blob->cbData = tracker.written; 00889 } 00890 } 00891 TRACE("returning %d\n", ret); 00892 return ret; 00893 } 00894 00895 BOOL WINAPI CertSaveStore(HCERTSTORE hCertStore, DWORD dwMsgAndCertEncodingType, 00896 DWORD dwSaveAs, DWORD dwSaveTo, void *pvSaveToPara, DWORD dwFlags) 00897 { 00898 BOOL (*saveFunc)(HCERTSTORE, DWORD, void *); 00899 void *handle; 00900 BOOL ret, closeFile = TRUE; 00901 00902 TRACE("(%p, %08x, %d, %d, %p, %08x)\n", hCertStore, 00903 dwMsgAndCertEncodingType, dwSaveAs, dwSaveTo, pvSaveToPara, dwFlags); 00904 00905 switch (dwSaveAs) 00906 { 00907 case CERT_STORE_SAVE_AS_STORE: 00908 if (dwSaveTo == CERT_STORE_SAVE_TO_MEMORY) 00909 saveFunc = CRYPT_SaveSerializedToMem; 00910 else 00911 saveFunc = CRYPT_SaveSerializedToFile; 00912 break; 00913 case CERT_STORE_SAVE_AS_PKCS7: 00914 if (dwSaveTo == CERT_STORE_SAVE_TO_MEMORY) 00915 saveFunc = CRYPT_SavePKCSToMem; 00916 else 00917 saveFunc = CRYPT_SavePKCSToFile; 00918 break; 00919 default: 00920 WARN("unimplemented for %d\n", dwSaveAs); 00921 SetLastError(ERROR_INVALID_PARAMETER); 00922 return FALSE; 00923 } 00924 switch (dwSaveTo) 00925 { 00926 case CERT_STORE_SAVE_TO_FILE: 00927 handle = pvSaveToPara; 00928 closeFile = FALSE; 00929 break; 00930 case CERT_STORE_SAVE_TO_FILENAME_A: 00931 handle = CreateFileA(pvSaveToPara, GENERIC_WRITE, 0, NULL, 00932 CREATE_ALWAYS, 0, NULL); 00933 break; 00934 case CERT_STORE_SAVE_TO_FILENAME_W: 00935 handle = CreateFileW(pvSaveToPara, GENERIC_WRITE, 0, NULL, 00936 CREATE_ALWAYS, 0, NULL); 00937 break; 00938 case CERT_STORE_SAVE_TO_MEMORY: 00939 handle = pvSaveToPara; 00940 break; 00941 default: 00942 WARN("unimplemented for %d\n", dwSaveTo); 00943 SetLastError(ERROR_INVALID_PARAMETER); 00944 return FALSE; 00945 } 00946 ret = saveFunc(hCertStore, dwMsgAndCertEncodingType, handle); 00947 if (closeFile) 00948 CloseHandle(handle); 00949 TRACE("returning %d\n", ret); 00950 return ret; 00951 } 00952 00953 BOOL WINAPI CertAddSerializedElementToStore(HCERTSTORE hCertStore, 00954 const BYTE *pbElement, DWORD cbElement, DWORD dwAddDisposition, DWORD dwFlags, 00955 DWORD dwContextTypeFlags, DWORD *pdwContentType, const void **ppvContext) 00956 { 00957 const void *context; 00958 DWORD type; 00959 BOOL ret; 00960 00961 TRACE("(%p, %p, %d, %08x, %08x, %08x, %p, %p)\n", hCertStore, 00962 pbElement, cbElement, dwAddDisposition, dwFlags, dwContextTypeFlags, 00963 pdwContentType, ppvContext); 00964 00965 /* Call the internal function, then delete the hashes. Tests show this 00966 * function uses real hash values, not whatever's stored in the hash 00967 * property. 00968 */ 00969 context = CRYPT_ReadSerializedElement(pbElement, cbElement, 00970 dwContextTypeFlags, &type); 00971 if (context) 00972 { 00973 const WINE_CONTEXT_INTERFACE *contextInterface = NULL; 00974 00975 switch (type) 00976 { 00977 case CERT_STORE_CERTIFICATE_CONTEXT: 00978 contextInterface = pCertInterface; 00979 break; 00980 case CERT_STORE_CRL_CONTEXT: 00981 contextInterface = pCRLInterface; 00982 break; 00983 case CERT_STORE_CTL_CONTEXT: 00984 contextInterface = pCTLInterface; 00985 break; 00986 default: 00987 SetLastError(E_INVALIDARG); 00988 } 00989 if (contextInterface) 00990 { 00991 contextInterface->setProp(context, CERT_HASH_PROP_ID, 0, NULL); 00992 contextInterface->setProp(context, CERT_MD5_HASH_PROP_ID, 0, NULL); 00993 contextInterface->setProp(context, CERT_SIGNATURE_HASH_PROP_ID, 0, 00994 NULL); 00995 if (pdwContentType) 00996 *pdwContentType = type; 00997 ret = contextInterface->addContextToStore(hCertStore, context, 00998 dwAddDisposition, ppvContext); 00999 contextInterface->free(context); 01000 } 01001 else 01002 ret = FALSE; 01003 } 01004 else 01005 ret = FALSE; 01006 return ret; 01007 } Generated on Sat May 26 2012 04:21:55 for ReactOS by
1.7.6.1
|