comctl32: Add a short test for the listview.
[wine/wine64.git] / dlls / crypt32 / serialize.c
blobb0765a71c98470eafe8caca30d46be087a565445
1 /*
2 * Copyright 2004-2006 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 #include <stdarg.h>
19 #include "windef.h"
20 #include "winbase.h"
21 #include "wincrypt.h"
22 #include "wine/debug.h"
23 #include "excpt.h"
24 #include "wine/exception.h"
25 #include "crypt32_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
29 /* An extended certificate property in serialized form is prefixed by this
30 * header.
32 typedef struct _WINE_CERT_PROP_HEADER
34 DWORD propID;
35 DWORD unknown; /* always 1 */
36 DWORD cb;
37 } WINE_CERT_PROP_HEADER, *PWINE_CERT_PROP_HEADER;
39 static BOOL CRYPT_SerializeStoreElement(const void *context,
40 const BYTE *encodedContext, DWORD cbEncodedContext, DWORD contextPropID,
41 PCWINE_CONTEXT_INTERFACE contextInterface, DWORD dwFlags, BYTE *pbElement,
42 DWORD *pcbElement)
44 BOOL ret;
46 TRACE("(%p, %p, %08lx, %p, %p)\n", context, contextInterface, dwFlags,
47 pbElement, pcbElement);
49 if (context)
51 DWORD bytesNeeded = sizeof(WINE_CERT_PROP_HEADER) + cbEncodedContext;
52 DWORD prop = 0;
54 ret = TRUE;
55 do {
56 prop = contextInterface->enumProps(context, prop);
57 if (prop)
59 DWORD propSize = 0;
61 ret = contextInterface->getProp(context, prop, NULL, &propSize);
62 if (ret)
63 bytesNeeded += sizeof(WINE_CERT_PROP_HEADER) + propSize;
65 } while (ret && prop != 0);
67 if (!pbElement)
69 *pcbElement = bytesNeeded;
70 ret = TRUE;
72 else if (*pcbElement < bytesNeeded)
74 *pcbElement = bytesNeeded;
75 SetLastError(ERROR_MORE_DATA);
76 ret = FALSE;
78 else
80 PWINE_CERT_PROP_HEADER hdr;
81 DWORD bufSize = 0;
82 LPBYTE buf = NULL;
84 prop = 0;
85 do {
86 prop = contextInterface->enumProps(context, prop);
87 if (prop)
89 DWORD propSize = 0;
91 ret = contextInterface->getProp(context, prop, NULL,
92 &propSize);
93 if (ret)
95 if (bufSize < propSize)
97 if (buf)
98 buf = CryptMemRealloc(buf, propSize);
99 else
100 buf = CryptMemAlloc(propSize);
101 bufSize = propSize;
103 if (buf)
105 ret = contextInterface->getProp(context, prop, buf,
106 &propSize);
107 if (ret)
109 hdr = (PWINE_CERT_PROP_HEADER)pbElement;
110 hdr->propID = prop;
111 hdr->unknown = 1;
112 hdr->cb = propSize;
113 pbElement += sizeof(WINE_CERT_PROP_HEADER);
114 if (propSize)
116 memcpy(pbElement, buf, propSize);
117 pbElement += propSize;
121 else
122 ret = FALSE;
125 } while (ret && prop != 0);
126 CryptMemFree(buf);
128 hdr = (PWINE_CERT_PROP_HEADER)pbElement;
129 hdr->propID = contextPropID;
130 hdr->unknown = 1;
131 hdr->cb = cbEncodedContext;
132 memcpy(pbElement + sizeof(WINE_CERT_PROP_HEADER),
133 encodedContext, cbEncodedContext);
136 else
137 ret = FALSE;
138 return ret;
141 BOOL WINAPI CertSerializeCertificateStoreElement(PCCERT_CONTEXT pCertContext,
142 DWORD dwFlags, BYTE *pbElement, DWORD *pcbElement)
144 return CRYPT_SerializeStoreElement(pCertContext,
145 pCertContext->pbCertEncoded, pCertContext->cbCertEncoded,
146 CERT_CERT_PROP_ID, pCertInterface, dwFlags, pbElement, pcbElement);
149 BOOL WINAPI CertSerializeCRLStoreElement(PCCRL_CONTEXT pCrlContext,
150 DWORD dwFlags, BYTE *pbElement, DWORD *pcbElement)
152 return CRYPT_SerializeStoreElement(pCrlContext,
153 pCrlContext->pbCrlEncoded, pCrlContext->cbCrlEncoded,
154 CERT_CRL_PROP_ID, pCRLInterface, dwFlags, pbElement, pcbElement);
157 BOOL WINAPI CertSerializeCTLStoreElement(PCCTL_CONTEXT pCtlContext,
158 DWORD dwFlags, BYTE *pbElement, DWORD *pcbElement)
160 return CRYPT_SerializeStoreElement(pCtlContext,
161 pCtlContext->pbCtlEncoded, pCtlContext->cbCtlEncoded,
162 CERT_CTL_PROP_ID, pCRLInterface, dwFlags, pbElement, pcbElement);
165 /* Looks for the property with ID propID in the buffer buf. Returns a pointer
166 * to its header if a valid header is found, NULL if not. Valid means the
167 * length of thte property won't overrun buf, and the unknown field is 1.
169 static const WINE_CERT_PROP_HEADER *CRYPT_findPropID(const BYTE *buf,
170 DWORD size, DWORD propID)
172 const WINE_CERT_PROP_HEADER *ret = NULL;
173 BOOL done = FALSE;
175 while (size && !ret && !done)
177 if (size < sizeof(WINE_CERT_PROP_HEADER))
179 SetLastError(CRYPT_E_FILE_ERROR);
180 done = TRUE;
182 else
184 const WINE_CERT_PROP_HEADER *hdr =
185 (const WINE_CERT_PROP_HEADER *)buf;
187 size -= sizeof(WINE_CERT_PROP_HEADER);
188 buf += sizeof(WINE_CERT_PROP_HEADER);
189 if (size < hdr->cb)
191 SetLastError(E_INVALIDARG);
192 done = TRUE;
194 else if (!hdr->propID)
196 /* assume a zero prop ID means the data are uninitialized, so
197 * stop looking.
199 done = TRUE;
201 else if (hdr->unknown != 1)
203 SetLastError(ERROR_FILE_NOT_FOUND);
204 done = TRUE;
206 else if (hdr->propID == propID)
207 ret = hdr;
208 else
210 buf += hdr->cb;
211 size -= hdr->cb;
215 return ret;
218 const void *CRYPT_ReadSerializedElement(const BYTE *pbElement, DWORD cbElement,
219 DWORD dwContextTypeFlags, DWORD *pdwContentType)
221 const void *context;
223 TRACE("(%p, %ld, %08lx, %p)\n", pbElement, cbElement, dwContextTypeFlags,
224 pdwContentType);
226 if (!cbElement)
228 SetLastError(ERROR_END_OF_MEDIA);
229 return NULL;
232 __TRY
234 const WINE_CONTEXT_INTERFACE *contextInterface = NULL;
235 const WINE_CERT_PROP_HEADER *hdr = NULL;
236 DWORD type = 0;
237 BOOL ret;
239 ret = TRUE;
240 context = NULL;
241 if (dwContextTypeFlags == CERT_STORE_ALL_CONTEXT_FLAG)
243 hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CERT_PROP_ID);
244 if (hdr)
245 type = CERT_STORE_CERTIFICATE_CONTEXT;
246 else
248 hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CRL_PROP_ID);
249 if (hdr)
250 type = CERT_STORE_CRL_CONTEXT;
251 else
253 hdr = CRYPT_findPropID(pbElement, cbElement,
254 CERT_CTL_PROP_ID);
255 if (hdr)
256 type = CERT_STORE_CTL_CONTEXT;
260 else if (dwContextTypeFlags & CERT_STORE_CERTIFICATE_CONTEXT_FLAG)
262 hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CERT_PROP_ID);
263 type = CERT_STORE_CERTIFICATE_CONTEXT;
265 else if (dwContextTypeFlags & CERT_STORE_CRL_CONTEXT_FLAG)
267 hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CRL_PROP_ID);
268 type = CERT_STORE_CRL_CONTEXT;
270 else if (dwContextTypeFlags & CERT_STORE_CTL_CONTEXT_FLAG)
272 hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CTL_PROP_ID);
273 type = CERT_STORE_CTL_CONTEXT;
276 switch (type)
278 case CERT_STORE_CERTIFICATE_CONTEXT:
279 contextInterface = pCertInterface;
280 break;
281 case CERT_STORE_CRL_CONTEXT:
282 contextInterface = pCRLInterface;
283 break;
284 case CERT_STORE_CTL_CONTEXT:
285 contextInterface = pCTLInterface;
286 break;
287 default:
288 SetLastError(E_INVALIDARG);
289 ret = FALSE;
291 if (!hdr)
292 ret = FALSE;
294 if (ret)
295 context = contextInterface->create(X509_ASN_ENCODING,
296 (BYTE *)hdr + sizeof(WINE_CERT_PROP_HEADER), hdr->cb);
297 if (ret && context)
299 BOOL noMoreProps = FALSE;
301 while (!noMoreProps && ret)
303 if (cbElement < sizeof(WINE_CERT_PROP_HEADER))
304 ret = FALSE;
305 else
307 const WINE_CERT_PROP_HEADER *hdr =
308 (const WINE_CERT_PROP_HEADER *)pbElement;
310 TRACE("prop is %ld\n", hdr->propID);
311 cbElement -= sizeof(WINE_CERT_PROP_HEADER);
312 pbElement += sizeof(WINE_CERT_PROP_HEADER);
313 if (cbElement < hdr->cb)
315 SetLastError(E_INVALIDARG);
316 ret = FALSE;
318 else if (!hdr->propID)
320 /* Like in CRYPT_findPropID, stop if the propID is zero
322 noMoreProps = TRUE;
324 else if (hdr->unknown != 1)
326 SetLastError(ERROR_FILE_NOT_FOUND);
327 ret = FALSE;
329 else if (hdr->propID != CERT_CERT_PROP_ID &&
330 hdr->propID != CERT_CRL_PROP_ID && hdr->propID !=
331 CERT_CTL_PROP_ID)
333 /* Have to create a blob for most types, but not
334 * for all.. arghh.
336 switch (hdr->propID)
338 case CERT_AUTO_ENROLL_PROP_ID:
339 case CERT_CTL_USAGE_PROP_ID:
340 case CERT_DESCRIPTION_PROP_ID:
341 case CERT_FRIENDLY_NAME_PROP_ID:
342 case CERT_HASH_PROP_ID:
343 case CERT_KEY_IDENTIFIER_PROP_ID:
344 case CERT_MD5_HASH_PROP_ID:
345 case CERT_NEXT_UPDATE_LOCATION_PROP_ID:
346 case CERT_PUBKEY_ALG_PARA_PROP_ID:
347 case CERT_PVK_FILE_PROP_ID:
348 case CERT_SIGNATURE_HASH_PROP_ID:
349 case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID:
350 case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID:
351 case CERT_ENROLLMENT_PROP_ID:
352 case CERT_CROSS_CERT_DIST_POINTS_PROP_ID:
353 case CERT_RENEWAL_PROP_ID:
355 CRYPT_DATA_BLOB blob = { hdr->cb,
356 (LPBYTE)pbElement };
358 ret = contextInterface->setProp(context,
359 hdr->propID, 0, &blob);
360 break;
362 case CERT_DATE_STAMP_PROP_ID:
363 ret = contextInterface->setProp(context,
364 hdr->propID, 0, pbElement);
365 break;
366 default:
367 FIXME("prop ID %ld: stub\n", hdr->propID);
370 pbElement += hdr->cb;
371 cbElement -= hdr->cb;
372 if (!cbElement)
373 noMoreProps = TRUE;
376 if (ret)
378 if (pdwContentType)
379 *pdwContentType = type;
381 else
383 contextInterface->free(context);
384 context = NULL;
388 __EXCEPT_PAGE_FAULT
390 SetLastError(STATUS_ACCESS_VIOLATION);
391 context = NULL;
393 __ENDTRY
394 return context;
397 BOOL WINAPI CertAddSerializedElementToStore(HCERTSTORE hCertStore,
398 const BYTE *pbElement, DWORD cbElement, DWORD dwAddDisposition, DWORD dwFlags,
399 DWORD dwContextTypeFlags, DWORD *pdwContentType, const void **ppvContext)
401 const void *context;
402 DWORD type;
403 BOOL ret;
405 TRACE("(%p, %p, %ld, %08lx, %08lx, %08lx, %p, %p)\n", hCertStore,
406 pbElement, cbElement, dwAddDisposition, dwFlags, dwContextTypeFlags,
407 pdwContentType, ppvContext);
409 /* Call the internal function, then delete the hashes. Tests show this
410 * function uses real hash values, not whatever's stored in the hash
411 * property.
413 context = CRYPT_ReadSerializedElement(pbElement, cbElement,
414 dwContextTypeFlags, &type);
415 if (context)
417 const WINE_CONTEXT_INTERFACE *contextInterface = NULL;
419 switch (type)
421 case CERT_STORE_CERTIFICATE_CONTEXT:
422 contextInterface = pCertInterface;
423 break;
424 case CERT_STORE_CRL_CONTEXT:
425 contextInterface = pCRLInterface;
426 break;
427 case CERT_STORE_CTL_CONTEXT:
428 contextInterface = pCTLInterface;
429 break;
430 default:
431 SetLastError(E_INVALIDARG);
433 if (contextInterface)
435 contextInterface->setProp(context, CERT_HASH_PROP_ID, 0, NULL);
436 contextInterface->setProp(context, CERT_MD5_HASH_PROP_ID, 0, NULL);
437 contextInterface->setProp(context, CERT_SIGNATURE_HASH_PROP_ID, 0,
438 NULL);
439 if (pdwContentType)
440 *pdwContentType = type;
441 ret = contextInterface->addContextToStore(hCertStore, context,
442 dwAddDisposition, ppvContext);
443 contextInterface->free(context);
445 else
446 ret = FALSE;
448 else
449 ret = FALSE;
450 return ret;