ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

serialize.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.