2 * Copyright 2004-2007 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
23 #include "wine/debug.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
32 typedef struct _WINE_CERT_PROP_HEADER
35 DWORD unknown
; /* always 1 */
37 } WINE_CERT_PROP_HEADER
;
39 struct store_CRYPT_KEY_PROV_INFO
41 DWORD pwszContainerName
;
50 struct store_CRYPT_KEY_PROV_PARAM
58 static DWORD
serialize_KeyProvInfoProperty(const CRYPT_KEY_PROV_INFO
*info
, struct store_CRYPT_KEY_PROV_INFO
**ret
)
60 struct store_CRYPT_KEY_PROV_INFO
*store
;
61 struct store_CRYPT_KEY_PROV_PARAM
*param
;
62 DWORD size
= sizeof(struct store_CRYPT_KEY_PROV_INFO
), i
;
65 if (info
->pwszContainerName
)
66 size
+= (lstrlenW(info
->pwszContainerName
) + 1) * sizeof(WCHAR
);
67 if (info
->pwszProvName
)
68 size
+= (lstrlenW(info
->pwszProvName
) + 1) * sizeof(WCHAR
);
70 for (i
= 0; i
< info
->cProvParam
; i
++)
71 size
+= sizeof(struct store_CRYPT_KEY_PROV_PARAM
) + info
->rgProvParam
[i
].cbData
;
73 if (!ret
) return size
;
75 store
= CryptMemAlloc(size
);
78 param
= (struct store_CRYPT_KEY_PROV_PARAM
*)(store
+ 1);
79 data
= (BYTE
*)param
+ sizeof(struct store_CRYPT_KEY_PROV_PARAM
) * info
->cProvParam
;
81 if (info
->pwszContainerName
)
83 store
->pwszContainerName
= data
- (BYTE
*)store
;
84 lstrcpyW((LPWSTR
)data
, info
->pwszContainerName
);
85 data
+= (lstrlenW(info
->pwszContainerName
) + 1) * sizeof(WCHAR
);
88 store
->pwszContainerName
= 0;
90 if (info
->pwszProvName
)
92 store
->pwszProvName
= data
- (BYTE
*)store
;
93 lstrcpyW((LPWSTR
)data
, info
->pwszProvName
);
94 data
+= (lstrlenW(info
->pwszProvName
) + 1) * sizeof(WCHAR
);
97 store
->pwszProvName
= 0;
99 store
->dwProvType
= info
->dwProvType
;
100 store
->dwFlags
= info
->dwFlags
;
101 store
->cProvParam
= info
->cProvParam
;
102 store
->rgProvParam
= info
->cProvParam
? (BYTE
*)param
- (BYTE
*)store
: 0;
103 store
->dwKeySpec
= info
->dwKeySpec
;
105 for (i
= 0; i
< info
->cProvParam
; i
++)
107 param
[i
].dwParam
= info
->rgProvParam
[i
].dwParam
;
108 param
[i
].dwFlags
= info
->rgProvParam
[i
].dwFlags
;
109 param
[i
].cbData
= info
->rgProvParam
[i
].cbData
;
110 param
[i
].pbData
= param
[i
].cbData
? data
- (BYTE
*)store
: 0;
111 memcpy(data
, info
->rgProvParam
[i
].pbData
, info
->rgProvParam
[i
].cbData
);
112 data
+= info
->rgProvParam
[i
].cbData
;
119 static BOOL
CRYPT_SerializeStoreElement(const void *context
,
120 const BYTE
*encodedContext
, DWORD cbEncodedContext
, DWORD contextPropID
,
121 const WINE_CONTEXT_INTERFACE
*contextInterface
, DWORD dwFlags
, BOOL omitHashes
,
122 BYTE
*pbElement
, DWORD
*pcbElement
)
126 TRACE("(%p, %p, %08lx, %d, %p, %p)\n", context
, contextInterface
, dwFlags
,
127 omitHashes
, pbElement
, pcbElement
);
131 DWORD bytesNeeded
= sizeof(WINE_CERT_PROP_HEADER
) + cbEncodedContext
;
136 prop
= contextInterface
->enumProps(context
, prop
);
137 if (prop
&& (!omitHashes
|| !IS_CERT_HASH_PROP_ID(prop
)))
141 ret
= contextInterface
->getProp(context
, prop
, NULL
, &propSize
);
144 if (prop
== CERT_KEY_PROV_INFO_PROP_ID
)
146 BYTE
*info
= CryptMemAlloc(propSize
);
147 contextInterface
->getProp(context
, prop
, info
, &propSize
);
148 propSize
= serialize_KeyProvInfoProperty((const CRYPT_KEY_PROV_INFO
*)info
, NULL
);
151 bytesNeeded
+= sizeof(WINE_CERT_PROP_HEADER
) + propSize
;
154 } while (ret
&& prop
!= 0);
158 *pcbElement
= bytesNeeded
;
161 else if (*pcbElement
< bytesNeeded
)
163 *pcbElement
= bytesNeeded
;
164 SetLastError(ERROR_MORE_DATA
);
169 WINE_CERT_PROP_HEADER
*hdr
;
175 prop
= contextInterface
->enumProps(context
, prop
);
176 if (prop
&& (!omitHashes
|| !IS_CERT_HASH_PROP_ID(prop
)))
180 ret
= contextInterface
->getProp(context
, prop
, NULL
,
184 if (bufSize
< propSize
)
187 buf
= CryptMemRealloc(buf
, propSize
);
189 buf
= CryptMemAlloc(propSize
);
194 ret
= contextInterface
->getProp(context
, prop
, buf
,
198 if (prop
== CERT_KEY_PROV_INFO_PROP_ID
)
200 struct store_CRYPT_KEY_PROV_INFO
*store
;
201 propSize
= serialize_KeyProvInfoProperty((const CRYPT_KEY_PROV_INFO
*)buf
, &store
);
206 hdr
= (WINE_CERT_PROP_HEADER
*)pbElement
;
210 pbElement
+= sizeof(WINE_CERT_PROP_HEADER
);
213 memcpy(pbElement
, buf
, propSize
);
214 pbElement
+= propSize
;
222 } while (ret
&& prop
!= 0);
225 hdr
= (WINE_CERT_PROP_HEADER
*)pbElement
;
226 hdr
->propID
= contextPropID
;
228 hdr
->cb
= cbEncodedContext
;
229 memcpy(pbElement
+ sizeof(WINE_CERT_PROP_HEADER
),
230 encodedContext
, cbEncodedContext
);
238 BOOL WINAPI
CertSerializeCertificateStoreElement(PCCERT_CONTEXT pCertContext
,
239 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
241 return CRYPT_SerializeStoreElement(pCertContext
,
242 pCertContext
->pbCertEncoded
, pCertContext
->cbCertEncoded
,
243 CERT_CERT_PROP_ID
, pCertInterface
, dwFlags
, FALSE
, pbElement
, pcbElement
);
246 BOOL WINAPI
CertSerializeCRLStoreElement(PCCRL_CONTEXT pCrlContext
,
247 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
249 return CRYPT_SerializeStoreElement(pCrlContext
,
250 pCrlContext
->pbCrlEncoded
, pCrlContext
->cbCrlEncoded
,
251 CERT_CRL_PROP_ID
, pCRLInterface
, dwFlags
, FALSE
, pbElement
, pcbElement
);
254 BOOL WINAPI
CertSerializeCTLStoreElement(PCCTL_CONTEXT pCtlContext
,
255 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
257 return CRYPT_SerializeStoreElement(pCtlContext
,
258 pCtlContext
->pbCtlEncoded
, pCtlContext
->cbCtlEncoded
,
259 CERT_CTL_PROP_ID
, pCTLInterface
, dwFlags
, FALSE
, pbElement
, pcbElement
);
262 /* Looks for the property with ID propID in the buffer buf. Returns a pointer
263 * to its header if a valid header is found, NULL if not. Valid means the
264 * length of the property won't overrun buf, and the unknown field is 1.
266 static const WINE_CERT_PROP_HEADER
*CRYPT_findPropID(const BYTE
*buf
,
267 DWORD size
, DWORD propID
)
269 const WINE_CERT_PROP_HEADER
*ret
= NULL
;
272 while (size
&& !ret
&& !done
)
274 if (size
< sizeof(WINE_CERT_PROP_HEADER
))
276 SetLastError(CRYPT_E_FILE_ERROR
);
281 const WINE_CERT_PROP_HEADER
*hdr
=
282 (const WINE_CERT_PROP_HEADER
*)buf
;
284 size
-= sizeof(WINE_CERT_PROP_HEADER
);
285 buf
+= sizeof(WINE_CERT_PROP_HEADER
);
288 SetLastError(E_INVALIDARG
);
291 else if (!hdr
->propID
)
293 /* assume a zero prop ID means the data are uninitialized, so
298 else if (hdr
->unknown
!= 1)
300 SetLastError(ERROR_FILE_NOT_FOUND
);
303 else if (hdr
->propID
== propID
)
315 static DWORD
read_serialized_KeyProvInfoProperty(const struct store_CRYPT_KEY_PROV_INFO
*store
, CRYPT_KEY_PROV_INFO
**ret
)
317 const struct store_CRYPT_KEY_PROV_PARAM
*param
;
318 CRYPT_KEY_PROV_INFO
*info
;
319 DWORD size
= sizeof(CRYPT_KEY_PROV_INFO
), i
;
323 base
= (const BYTE
*)store
;
324 param
= (const struct store_CRYPT_KEY_PROV_PARAM
*)(base
+ store
->rgProvParam
);
326 if (store
->pwszContainerName
)
327 size
+= (lstrlenW((LPCWSTR
)(base
+ store
->pwszContainerName
)) + 1) * sizeof(WCHAR
);
328 if (store
->pwszProvName
)
329 size
+= (lstrlenW((LPCWSTR
)(base
+ store
->pwszProvName
)) + 1) * sizeof(WCHAR
);
331 for (i
= 0; i
< store
->cProvParam
; i
++)
332 size
+= sizeof(CRYPT_KEY_PROV_PARAM
) + param
[i
].cbData
;
334 info
= CryptMemAlloc(size
);
337 SetLastError(ERROR_OUTOFMEMORY
);
341 data
= (BYTE
*)(info
+ 1) + sizeof(CRYPT_KEY_PROV_PARAM
) * store
->cProvParam
;
343 if (store
->pwszContainerName
)
345 info
->pwszContainerName
= (LPWSTR
)data
;
346 lstrcpyW(info
->pwszContainerName
, (LPCWSTR
)((const BYTE
*)store
+ store
->pwszContainerName
));
347 data
+= (lstrlenW(info
->pwszContainerName
) + 1) * sizeof(WCHAR
);
350 info
->pwszContainerName
= NULL
;
352 if (store
->pwszProvName
)
354 info
->pwszProvName
= (LPWSTR
)data
;
355 lstrcpyW(info
->pwszProvName
, (LPCWSTR
)((const BYTE
*)store
+ store
->pwszProvName
));
356 data
+= (lstrlenW(info
->pwszProvName
) + 1) * sizeof(WCHAR
);
359 info
->pwszProvName
= NULL
;
361 info
->dwProvType
= store
->dwProvType
;
362 info
->dwFlags
= store
->dwFlags
;
363 info
->dwKeySpec
= store
->dwKeySpec
;
364 info
->cProvParam
= store
->cProvParam
;
366 if (info
->cProvParam
)
370 info
->rgProvParam
= (CRYPT_KEY_PROV_PARAM
*)(info
+ 1);
372 for (i
= 0; i
< info
->cProvParam
; i
++)
374 info
->rgProvParam
[i
].dwParam
= param
[i
].dwParam
;
375 info
->rgProvParam
[i
].dwFlags
= param
[i
].dwFlags
;
376 info
->rgProvParam
[i
].cbData
= param
[i
].cbData
;
377 info
->rgProvParam
[i
].pbData
= param
[i
].cbData
? data
: NULL
;
378 memcpy(info
->rgProvParam
[i
].pbData
, base
+ param
[i
].pbData
, param
[i
].cbData
);
379 data
+= param
[i
].cbData
;
383 info
->rgProvParam
= NULL
;
385 TRACE("%s,%s,%lu,%08lx,%lu,%p,%lu\n", debugstr_w(info
->pwszContainerName
), debugstr_w(info
->pwszProvName
),
386 info
->dwProvType
, info
->dwFlags
, info
->cProvParam
, info
->rgProvParam
, info
->dwKeySpec
);
392 static BOOL
CRYPT_ReadContextProp(
393 const WINE_CONTEXT_INTERFACE
*contextInterface
, const void *context
,
394 const WINE_CERT_PROP_HEADER
*hdr
, const BYTE
*pbElement
, DWORD cbElement
)
398 if (cbElement
< hdr
->cb
)
400 SetLastError(E_INVALIDARG
);
403 else if (hdr
->unknown
!= 1)
405 SetLastError(ERROR_FILE_NOT_FOUND
);
408 else if (hdr
->propID
>= CERT_FIRST_USER_PROP_ID
&& hdr
->propID
<= CERT_LAST_USER_PROP_ID
)
410 CRYPT_DATA_BLOB blob
= { hdr
->cb
, (LPBYTE
)pbElement
};
412 ret
= contextInterface
->setProp(context
, hdr
->propID
, 0, &blob
);
414 else if (hdr
->propID
!= CERT_CERT_PROP_ID
&&
415 hdr
->propID
!= CERT_CRL_PROP_ID
&& hdr
->propID
!= CERT_CTL_PROP_ID
)
417 /* Have to create a blob for most types, but not
422 case CERT_AUTO_ENROLL_PROP_ID
:
423 case CERT_CTL_USAGE_PROP_ID
:
424 case CERT_DESCRIPTION_PROP_ID
:
425 case CERT_FRIENDLY_NAME_PROP_ID
:
426 case CERT_HASH_PROP_ID
:
427 case CERT_KEY_IDENTIFIER_PROP_ID
:
428 case CERT_MD5_HASH_PROP_ID
:
429 case CERT_NEXT_UPDATE_LOCATION_PROP_ID
:
430 case CERT_PUBKEY_ALG_PARA_PROP_ID
:
431 case CERT_PVK_FILE_PROP_ID
:
432 case CERT_SIGNATURE_HASH_PROP_ID
:
433 case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID
:
434 case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID
:
435 case CERT_ENROLLMENT_PROP_ID
:
436 case CERT_CROSS_CERT_DIST_POINTS_PROP_ID
:
437 case CERT_RENEWAL_PROP_ID
:
439 CRYPT_DATA_BLOB blob
= { hdr
->cb
,
442 ret
= contextInterface
->setProp(context
,
443 hdr
->propID
, 0, &blob
);
446 case CERT_DATE_STAMP_PROP_ID
:
447 ret
= contextInterface
->setProp(context
,
448 hdr
->propID
, 0, pbElement
);
450 case CERT_KEY_PROV_INFO_PROP_ID
:
452 CRYPT_KEY_PROV_INFO
*info
;
454 if (read_serialized_KeyProvInfoProperty((const struct store_CRYPT_KEY_PROV_INFO
*)pbElement
, &info
))
456 ret
= contextInterface
->setProp(context
, hdr
->propID
, 0, info
);
463 case CERT_KEY_CONTEXT_PROP_ID
:
465 CERT_KEY_CONTEXT ctx
;
466 CRYPT_ConvertKeyContext((struct store_CERT_KEY_CONTEXT
*)pbElement
, &ctx
);
467 ret
= contextInterface
->setProp(context
, hdr
->propID
, 0, &ctx
);
476 /* ignore the context itself */
482 const void *CRYPT_ReadSerializedElement(const BYTE
*pbElement
, DWORD cbElement
,
483 DWORD dwContextTypeFlags
, DWORD
*pdwContentType
)
487 TRACE("(%p, %ld, %08lx, %p)\n", pbElement
, cbElement
, dwContextTypeFlags
,
492 SetLastError(ERROR_END_OF_MEDIA
);
498 const WINE_CONTEXT_INTERFACE
*contextInterface
= NULL
;
499 const WINE_CERT_PROP_HEADER
*hdr
= NULL
;
505 if (dwContextTypeFlags
== CERT_STORE_ALL_CONTEXT_FLAG
)
507 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CERT_PROP_ID
);
509 type
= CERT_STORE_CERTIFICATE_CONTEXT
;
512 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CRL_PROP_ID
);
514 type
= CERT_STORE_CRL_CONTEXT
;
517 hdr
= CRYPT_findPropID(pbElement
, cbElement
,
520 type
= CERT_STORE_CTL_CONTEXT
;
524 else if (dwContextTypeFlags
& CERT_STORE_CERTIFICATE_CONTEXT_FLAG
)
526 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CERT_PROP_ID
);
527 type
= CERT_STORE_CERTIFICATE_CONTEXT
;
529 else if (dwContextTypeFlags
& CERT_STORE_CRL_CONTEXT_FLAG
)
531 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CRL_PROP_ID
);
532 type
= CERT_STORE_CRL_CONTEXT
;
534 else if (dwContextTypeFlags
& CERT_STORE_CTL_CONTEXT_FLAG
)
536 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CTL_PROP_ID
);
537 type
= CERT_STORE_CTL_CONTEXT
;
542 case CERT_STORE_CERTIFICATE_CONTEXT
:
543 contextInterface
= pCertInterface
;
545 case CERT_STORE_CRL_CONTEXT
:
546 contextInterface
= pCRLInterface
;
548 case CERT_STORE_CTL_CONTEXT
:
549 contextInterface
= pCTLInterface
;
552 SetLastError(E_INVALIDARG
);
559 context
= contextInterface
->create(X509_ASN_ENCODING
,
560 (BYTE
*)hdr
+ sizeof(WINE_CERT_PROP_HEADER
), hdr
->cb
);
563 BOOL noMoreProps
= FALSE
;
565 while (!noMoreProps
&& ret
)
567 if (cbElement
< sizeof(WINE_CERT_PROP_HEADER
))
571 const WINE_CERT_PROP_HEADER
*hdr
=
572 (const WINE_CERT_PROP_HEADER
*)pbElement
;
574 TRACE("prop is %ld\n", hdr
->propID
);
575 cbElement
-= sizeof(WINE_CERT_PROP_HEADER
);
576 pbElement
+= sizeof(WINE_CERT_PROP_HEADER
);
579 /* Like in CRYPT_findPropID, stop if the propID is zero
584 ret
= CRYPT_ReadContextProp(contextInterface
, context
,
585 hdr
, pbElement
, cbElement
);
586 pbElement
+= hdr
->cb
;
587 cbElement
-= hdr
->cb
;
595 *pdwContentType
= type
;
599 Context_Release(context_from_ptr(context
));
606 SetLastError(STATUS_ACCESS_VIOLATION
);
613 static const BYTE fileHeader
[] = { 0, 0, 0, 0, 'C','E','R','T' };
615 typedef BOOL (*read_serialized_func
)(void *handle
, void *buffer
,
616 DWORD bytesToRead
, DWORD
*bytesRead
);
618 static BOOL
CRYPT_ReadSerializedStore(void *handle
,
619 read_serialized_func read_func
, HCERTSTORE store
)
621 BYTE fileHeaderBuf
[sizeof(fileHeader
)];
625 /* Failure reading is non-critical, we'll leave the store empty */
626 ret
= read_func(handle
, fileHeaderBuf
, sizeof(fileHeaderBuf
), &read
);
630 ; /* an empty file is okay */
631 else if (read
!= sizeof(fileHeaderBuf
))
633 else if (!memcmp(fileHeaderBuf
, fileHeader
, read
))
635 WINE_CERT_PROP_HEADER propHdr
;
636 const void *context
= NULL
;
637 const WINE_CONTEXT_INTERFACE
*contextInterface
= NULL
;
642 ret
= read_func(handle
, &propHdr
, sizeof(propHdr
), &read
);
643 if (ret
&& read
== sizeof(propHdr
))
645 if (contextInterface
&& context
&&
646 (propHdr
.propID
== CERT_CERT_PROP_ID
||
647 propHdr
.propID
== CERT_CRL_PROP_ID
||
648 propHdr
.propID
== CERT_CTL_PROP_ID
))
650 /* We have a new context, so free the existing one */
651 Context_Release(context_from_ptr(context
));
653 if (propHdr
.cb
> bufSize
)
655 /* Not reusing realloc, because the old data aren't
659 buf
= CryptMemAlloc(propHdr
.cb
);
660 bufSize
= propHdr
.cb
;
663 ; /* Property is empty, nothing to do */
666 ret
= read_func(handle
, buf
, propHdr
.cb
, &read
);
667 if (ret
&& read
== propHdr
.cb
)
669 if (propHdr
.propID
== CERT_CERT_PROP_ID
)
671 contextInterface
= pCertInterface
;
672 ret
= contextInterface
->addEncodedToStore(store
,
673 X509_ASN_ENCODING
, buf
, read
,
674 CERT_STORE_ADD_NEW
, &context
);
676 else if (propHdr
.propID
== CERT_CRL_PROP_ID
)
678 contextInterface
= pCRLInterface
;
679 ret
= contextInterface
->addEncodedToStore(store
,
680 X509_ASN_ENCODING
, buf
, read
,
681 CERT_STORE_ADD_NEW
, &context
);
683 else if (propHdr
.propID
== CERT_CTL_PROP_ID
)
685 contextInterface
= pCTLInterface
;
686 ret
= contextInterface
->addEncodedToStore(store
,
687 X509_ASN_ENCODING
, buf
, read
,
688 CERT_STORE_ADD_NEW
, &context
);
692 if (!contextInterface
)
694 WARN("prop id %ld before a context id\n",
699 ret
= CRYPT_ReadContextProp(
700 contextInterface
, context
, &propHdr
, buf
,
708 } while (ret
&& read
> 0 && propHdr
.cb
);
709 if (contextInterface
&& context
)
711 /* Free the last context added */
712 Context_Release(context_from_ptr(context
));
725 static BOOL
read_file_wrapper(void *handle
, void *buffer
, DWORD bytesToRead
,
728 return ReadFile(handle
, buffer
, bytesToRead
, bytesRead
, NULL
);
731 BOOL
CRYPT_ReadSerializedStoreFromFile(HANDLE file
, HCERTSTORE store
)
733 return CRYPT_ReadSerializedStore(file
, read_file_wrapper
, store
);
738 const CRYPT_DATA_BLOB
*blob
;
742 static BOOL
read_blob_wrapper(void *handle
, void *buffer
, DWORD bytesToRead
,
745 struct BlobReader
*reader
= handle
;
748 if (reader
->current
< reader
->blob
->cbData
)
750 *bytesRead
= min(bytesToRead
, reader
->blob
->cbData
- reader
->current
);
751 memcpy(buffer
, reader
->blob
->pbData
+ reader
->current
, *bytesRead
);
752 reader
->current
+= *bytesRead
;
755 else if (reader
->current
== reader
->blob
->cbData
)
765 BOOL
CRYPT_ReadSerializedStoreFromBlob(const CRYPT_DATA_BLOB
*blob
,
768 struct BlobReader reader
= { blob
, 0 };
770 return CRYPT_ReadSerializedStore(&reader
, read_blob_wrapper
, store
);
773 static BOOL WINAPI
CRYPT_SerializeCertNoHash(PCCERT_CONTEXT pCertContext
,
774 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
776 return CRYPT_SerializeStoreElement(pCertContext
,
777 pCertContext
->pbCertEncoded
, pCertContext
->cbCertEncoded
,
778 CERT_CERT_PROP_ID
, pCertInterface
, dwFlags
, TRUE
, pbElement
, pcbElement
);
781 static BOOL WINAPI
CRYPT_SerializeCRLNoHash(PCCRL_CONTEXT pCrlContext
,
782 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
784 return CRYPT_SerializeStoreElement(pCrlContext
,
785 pCrlContext
->pbCrlEncoded
, pCrlContext
->cbCrlEncoded
,
786 CERT_CRL_PROP_ID
, pCRLInterface
, dwFlags
, TRUE
, pbElement
, pcbElement
);
789 static BOOL WINAPI
CRYPT_SerializeCTLNoHash(PCCTL_CONTEXT pCtlContext
,
790 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
792 return CRYPT_SerializeStoreElement(pCtlContext
,
793 pCtlContext
->pbCtlEncoded
, pCtlContext
->cbCtlEncoded
,
794 CERT_CTL_PROP_ID
, pCTLInterface
, dwFlags
, TRUE
, pbElement
, pcbElement
);
797 typedef BOOL (*SerializedOutputFunc
)(void *handle
, const void *buffer
,
800 static BOOL
CRYPT_SerializeContextsToStream(SerializedOutputFunc output
,
801 void *handle
, const WINE_CONTEXT_INTERFACE
*contextInterface
, HCERTSTORE store
)
803 const void *context
= NULL
;
807 context
= contextInterface
->enumContextsInStore(store
, context
);
813 ret
= contextInterface
->serialize(context
, 0, NULL
, &size
);
815 buf
= CryptMemAlloc(size
);
818 ret
= contextInterface
->serialize(context
, 0, buf
, &size
);
820 ret
= output(handle
, buf
, size
);
826 } while (ret
&& context
!= NULL
);
828 Context_Release(context_from_ptr(context
));
832 static BOOL
CRYPT_WriteSerializedStoreToStream(HCERTSTORE store
,
833 SerializedOutputFunc output
, void *handle
)
835 static const BYTE fileTrailer
[12] = { 0 };
836 WINE_CONTEXT_INTERFACE interface
;
839 ret
= output(handle
, fileHeader
, sizeof(fileHeader
));
842 interface
= *pCertInterface
;
843 interface
.serialize
= (SerializeElementFunc
)CRYPT_SerializeCertNoHash
;
844 ret
= CRYPT_SerializeContextsToStream(output
, handle
, &interface
,
849 interface
= *pCRLInterface
;
850 interface
.serialize
= (SerializeElementFunc
)CRYPT_SerializeCRLNoHash
;
851 ret
= CRYPT_SerializeContextsToStream(output
, handle
, &interface
,
856 interface
= *pCTLInterface
;
857 interface
.serialize
= (SerializeElementFunc
)CRYPT_SerializeCTLNoHash
;
858 ret
= CRYPT_SerializeContextsToStream(output
, handle
, &interface
,
862 ret
= output(handle
, fileTrailer
, sizeof(fileTrailer
));
866 static BOOL
CRYPT_FileOutputFunc(void *handle
, const void *buffer
, DWORD size
)
868 return WriteFile(handle
, buffer
, size
, &size
, NULL
);
871 static BOOL
CRYPT_WriteSerializedStoreToFile(HANDLE file
, HCERTSTORE store
)
873 SetFilePointer(file
, 0, NULL
, FILE_BEGIN
);
874 return CRYPT_WriteSerializedStoreToStream(store
, CRYPT_FileOutputFunc
,
878 static BOOL
CRYPT_SavePKCSToMem(HCERTSTORE store
,
879 DWORD dwMsgAndCertEncodingType
, void *handle
)
881 CERT_BLOB
*blob
= handle
;
882 CRYPT_SIGNED_INFO signedInfo
= { 0 };
883 PCCERT_CONTEXT cert
= NULL
;
884 PCCRL_CONTEXT crl
= NULL
;
888 TRACE("(%ld, %p)\n", blob
->pbData
? blob
->cbData
: 0, blob
->pbData
);
891 cert
= CertEnumCertificatesInStore(store
, cert
);
893 signedInfo
.cCertEncoded
++;
895 if (signedInfo
.cCertEncoded
)
897 signedInfo
.rgCertEncoded
= CryptMemAlloc(
898 signedInfo
.cCertEncoded
* sizeof(CERT_BLOB
));
899 if (!signedInfo
.rgCertEncoded
)
901 SetLastError(ERROR_OUTOFMEMORY
);
909 cert
= CertEnumCertificatesInStore(store
, cert
);
912 signedInfo
.rgCertEncoded
[i
].cbData
= cert
->cbCertEncoded
;
913 signedInfo
.rgCertEncoded
[i
].pbData
= cert
->pbCertEncoded
;
921 crl
= CertEnumCRLsInStore(store
, crl
);
923 signedInfo
.cCrlEncoded
++;
925 if (signedInfo
.cCrlEncoded
)
927 signedInfo
.rgCrlEncoded
= CryptMemAlloc(
928 signedInfo
.cCrlEncoded
* sizeof(CERT_BLOB
));
929 if (!signedInfo
.rgCrlEncoded
)
931 SetLastError(ERROR_OUTOFMEMORY
);
939 crl
= CertEnumCRLsInStore(store
, crl
);
942 signedInfo
.rgCrlEncoded
[i
].cbData
= crl
->cbCrlEncoded
;
943 signedInfo
.rgCrlEncoded
[i
].pbData
= crl
->pbCrlEncoded
;
951 ret
= CRYPT_AsnEncodeCMSSignedInfo(&signedInfo
, NULL
, &size
);
956 else if (blob
->cbData
< size
)
959 SetLastError(ERROR_MORE_DATA
);
965 ret
= CRYPT_AsnEncodeCMSSignedInfo(&signedInfo
, blob
->pbData
,
970 CryptMemFree(signedInfo
.rgCertEncoded
);
971 CryptMemFree(signedInfo
.rgCrlEncoded
);
972 TRACE("returning %d\n", ret
);
976 static BOOL
CRYPT_SavePKCSToFile(HCERTSTORE store
,
977 DWORD dwMsgAndCertEncodingType
, void *handle
)
979 CERT_BLOB blob
= { 0, NULL
};
982 TRACE("(%p)\n", handle
);
984 ret
= CRYPT_SavePKCSToMem(store
, dwMsgAndCertEncodingType
, &blob
);
987 blob
.pbData
= CryptMemAlloc(blob
.cbData
);
990 ret
= CRYPT_SavePKCSToMem(store
, dwMsgAndCertEncodingType
, &blob
);
992 ret
= WriteFile(handle
, blob
.pbData
, blob
.cbData
,
997 SetLastError(ERROR_OUTOFMEMORY
);
1001 TRACE("returning %d\n", ret
);
1005 static BOOL
CRYPT_SaveSerializedToFile(HCERTSTORE store
,
1006 DWORD dwMsgAndCertEncodingType
, void *handle
)
1008 return CRYPT_WriteSerializedStoreToFile(handle
, store
);
1011 struct MemWrittenTracker
1018 /* handle is a pointer to a MemWrittenTracker. Assumes its pointer is valid. */
1019 static BOOL
CRYPT_MemOutputFunc(void *handle
, const void *buffer
, DWORD size
)
1021 struct MemWrittenTracker
*tracker
= handle
;
1024 if (tracker
->written
+ size
> tracker
->cbData
)
1026 SetLastError(ERROR_MORE_DATA
);
1027 /* Update written so caller can notify its caller of the required size
1029 tracker
->written
+= size
;
1034 memcpy(tracker
->pbData
+ tracker
->written
, buffer
, size
);
1035 tracker
->written
+= size
;
1041 static BOOL
CRYPT_CountSerializedBytes(void *handle
, const void *buffer
,
1044 *(DWORD
*)handle
+= size
;
1048 static BOOL
CRYPT_SaveSerializedToMem(HCERTSTORE store
,
1049 DWORD dwMsgAndCertEncodingType
, void *handle
)
1051 CERT_BLOB
*blob
= handle
;
1055 ret
= CRYPT_WriteSerializedStoreToStream(store
, CRYPT_CountSerializedBytes
,
1060 blob
->cbData
= size
;
1061 else if (blob
->cbData
< size
)
1063 SetLastError(ERROR_MORE_DATA
);
1064 blob
->cbData
= size
;
1069 struct MemWrittenTracker tracker
= { blob
->cbData
, blob
->pbData
,
1072 ret
= CRYPT_WriteSerializedStoreToStream(store
, CRYPT_MemOutputFunc
,
1074 if (!ret
&& GetLastError() == ERROR_MORE_DATA
)
1075 blob
->cbData
= tracker
.written
;
1078 TRACE("returning %d\n", ret
);
1082 BOOL WINAPI
CertSaveStore(HCERTSTORE hCertStore
, DWORD dwMsgAndCertEncodingType
,
1083 DWORD dwSaveAs
, DWORD dwSaveTo
, void *pvSaveToPara
, DWORD dwFlags
)
1085 BOOL (*saveFunc
)(HCERTSTORE
, DWORD
, void *);
1087 BOOL ret
, closeFile
= TRUE
;
1089 TRACE("(%p, %08lx, %ld, %ld, %p, %08lx)\n", hCertStore
,
1090 dwMsgAndCertEncodingType
, dwSaveAs
, dwSaveTo
, pvSaveToPara
, dwFlags
);
1094 case CERT_STORE_SAVE_AS_STORE
:
1095 if (dwSaveTo
== CERT_STORE_SAVE_TO_MEMORY
)
1096 saveFunc
= CRYPT_SaveSerializedToMem
;
1098 saveFunc
= CRYPT_SaveSerializedToFile
;
1100 case CERT_STORE_SAVE_AS_PKCS7
:
1101 if (dwSaveTo
== CERT_STORE_SAVE_TO_MEMORY
)
1102 saveFunc
= CRYPT_SavePKCSToMem
;
1104 saveFunc
= CRYPT_SavePKCSToFile
;
1107 WARN("unimplemented for %ld\n", dwSaveAs
);
1108 SetLastError(ERROR_INVALID_PARAMETER
);
1113 case CERT_STORE_SAVE_TO_FILE
:
1114 handle
= pvSaveToPara
;
1117 case CERT_STORE_SAVE_TO_FILENAME_A
:
1118 handle
= CreateFileA(pvSaveToPara
, GENERIC_WRITE
, 0, NULL
,
1119 CREATE_ALWAYS
, 0, NULL
);
1121 case CERT_STORE_SAVE_TO_FILENAME_W
:
1122 handle
= CreateFileW(pvSaveToPara
, GENERIC_WRITE
, 0, NULL
,
1123 CREATE_ALWAYS
, 0, NULL
);
1125 case CERT_STORE_SAVE_TO_MEMORY
:
1126 handle
= pvSaveToPara
;
1129 WARN("unimplemented for %ld\n", dwSaveTo
);
1130 SetLastError(ERROR_INVALID_PARAMETER
);
1133 ret
= saveFunc(hCertStore
, dwMsgAndCertEncodingType
, handle
);
1135 CloseHandle(handle
);
1136 TRACE("returning %d\n", ret
);
1140 BOOL WINAPI
CertAddSerializedElementToStore(HCERTSTORE hCertStore
,
1141 const BYTE
*pbElement
, DWORD cbElement
, DWORD dwAddDisposition
, DWORD dwFlags
,
1142 DWORD dwContextTypeFlags
, DWORD
*pdwContentType
, const void **ppvContext
)
1144 const void *context
;
1148 TRACE("(%p, %p, %ld, %08lx, %08lx, %08lx, %p, %p)\n", hCertStore
,
1149 pbElement
, cbElement
, dwAddDisposition
, dwFlags
, dwContextTypeFlags
,
1150 pdwContentType
, ppvContext
);
1152 /* Call the internal function, then delete the hashes. Tests show this
1153 * function uses real hash values, not whatever's stored in the hash
1156 context
= CRYPT_ReadSerializedElement(pbElement
, cbElement
,
1157 dwContextTypeFlags
, &type
);
1160 const WINE_CONTEXT_INTERFACE
*contextInterface
= NULL
;
1164 case CERT_STORE_CERTIFICATE_CONTEXT
:
1165 contextInterface
= pCertInterface
;
1167 case CERT_STORE_CRL_CONTEXT
:
1168 contextInterface
= pCRLInterface
;
1170 case CERT_STORE_CTL_CONTEXT
:
1171 contextInterface
= pCTLInterface
;
1174 SetLastError(E_INVALIDARG
);
1176 if (contextInterface
)
1178 contextInterface
->setProp(context
, CERT_HASH_PROP_ID
, 0, NULL
);
1179 contextInterface
->setProp(context
, CERT_MD5_HASH_PROP_ID
, 0, NULL
);
1180 contextInterface
->setProp(context
, CERT_SIGNATURE_HASH_PROP_ID
, 0,
1183 *pdwContentType
= type
;
1184 ret
= contextInterface
->addContextToStore(hCertStore
, context
,
1185 dwAddDisposition
, ppvContext
);
1186 Context_Release(context_from_ptr(context
));