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_CERT_PROP_ID
&&
409 hdr
->propID
!= CERT_CRL_PROP_ID
&& hdr
->propID
!= CERT_CTL_PROP_ID
)
411 /* Have to create a blob for most types, but not
416 case CERT_AUTO_ENROLL_PROP_ID
:
417 case CERT_CTL_USAGE_PROP_ID
:
418 case CERT_DESCRIPTION_PROP_ID
:
419 case CERT_FRIENDLY_NAME_PROP_ID
:
420 case CERT_HASH_PROP_ID
:
421 case CERT_KEY_IDENTIFIER_PROP_ID
:
422 case CERT_MD5_HASH_PROP_ID
:
423 case CERT_NEXT_UPDATE_LOCATION_PROP_ID
:
424 case CERT_PUBKEY_ALG_PARA_PROP_ID
:
425 case CERT_PVK_FILE_PROP_ID
:
426 case CERT_SIGNATURE_HASH_PROP_ID
:
427 case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID
:
428 case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID
:
429 case CERT_ENROLLMENT_PROP_ID
:
430 case CERT_CROSS_CERT_DIST_POINTS_PROP_ID
:
431 case CERT_RENEWAL_PROP_ID
:
433 CRYPT_DATA_BLOB blob
= { hdr
->cb
,
436 ret
= contextInterface
->setProp(context
,
437 hdr
->propID
, 0, &blob
);
440 case CERT_DATE_STAMP_PROP_ID
:
441 ret
= contextInterface
->setProp(context
,
442 hdr
->propID
, 0, pbElement
);
444 case CERT_KEY_PROV_INFO_PROP_ID
:
446 CRYPT_KEY_PROV_INFO
*info
;
448 if (read_serialized_KeyProvInfoProperty((const struct store_CRYPT_KEY_PROV_INFO
*)pbElement
, &info
))
450 ret
= contextInterface
->setProp(context
, hdr
->propID
, 0, info
);
457 case CERT_KEY_CONTEXT_PROP_ID
:
459 CERT_KEY_CONTEXT ctx
;
460 CRYPT_ConvertKeyContext((struct store_CERT_KEY_CONTEXT
*)pbElement
, &ctx
);
461 ret
= contextInterface
->setProp(context
, hdr
->propID
, 0, &ctx
);
470 /* ignore the context itself */
476 const void *CRYPT_ReadSerializedElement(const BYTE
*pbElement
, DWORD cbElement
,
477 DWORD dwContextTypeFlags
, DWORD
*pdwContentType
)
481 TRACE("(%p, %ld, %08lx, %p)\n", pbElement
, cbElement
, dwContextTypeFlags
,
486 SetLastError(ERROR_END_OF_MEDIA
);
492 const WINE_CONTEXT_INTERFACE
*contextInterface
= NULL
;
493 const WINE_CERT_PROP_HEADER
*hdr
= NULL
;
499 if (dwContextTypeFlags
== CERT_STORE_ALL_CONTEXT_FLAG
)
501 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CERT_PROP_ID
);
503 type
= CERT_STORE_CERTIFICATE_CONTEXT
;
506 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CRL_PROP_ID
);
508 type
= CERT_STORE_CRL_CONTEXT
;
511 hdr
= CRYPT_findPropID(pbElement
, cbElement
,
514 type
= CERT_STORE_CTL_CONTEXT
;
518 else if (dwContextTypeFlags
& CERT_STORE_CERTIFICATE_CONTEXT_FLAG
)
520 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CERT_PROP_ID
);
521 type
= CERT_STORE_CERTIFICATE_CONTEXT
;
523 else if (dwContextTypeFlags
& CERT_STORE_CRL_CONTEXT_FLAG
)
525 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CRL_PROP_ID
);
526 type
= CERT_STORE_CRL_CONTEXT
;
528 else if (dwContextTypeFlags
& CERT_STORE_CTL_CONTEXT_FLAG
)
530 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CTL_PROP_ID
);
531 type
= CERT_STORE_CTL_CONTEXT
;
536 case CERT_STORE_CERTIFICATE_CONTEXT
:
537 contextInterface
= pCertInterface
;
539 case CERT_STORE_CRL_CONTEXT
:
540 contextInterface
= pCRLInterface
;
542 case CERT_STORE_CTL_CONTEXT
:
543 contextInterface
= pCTLInterface
;
546 SetLastError(E_INVALIDARG
);
553 context
= contextInterface
->create(X509_ASN_ENCODING
,
554 (BYTE
*)hdr
+ sizeof(WINE_CERT_PROP_HEADER
), hdr
->cb
);
557 BOOL noMoreProps
= FALSE
;
559 while (!noMoreProps
&& ret
)
561 if (cbElement
< sizeof(WINE_CERT_PROP_HEADER
))
565 const WINE_CERT_PROP_HEADER
*hdr
=
566 (const WINE_CERT_PROP_HEADER
*)pbElement
;
568 TRACE("prop is %ld\n", hdr
->propID
);
569 cbElement
-= sizeof(WINE_CERT_PROP_HEADER
);
570 pbElement
+= sizeof(WINE_CERT_PROP_HEADER
);
573 /* Like in CRYPT_findPropID, stop if the propID is zero
578 ret
= CRYPT_ReadContextProp(contextInterface
, context
,
579 hdr
, pbElement
, cbElement
);
580 pbElement
+= hdr
->cb
;
581 cbElement
-= hdr
->cb
;
589 *pdwContentType
= type
;
593 Context_Release(context_from_ptr(context
));
600 SetLastError(STATUS_ACCESS_VIOLATION
);
607 static const BYTE fileHeader
[] = { 0, 0, 0, 0, 'C','E','R','T' };
609 typedef BOOL (*read_serialized_func
)(void *handle
, void *buffer
,
610 DWORD bytesToRead
, DWORD
*bytesRead
);
612 static BOOL
CRYPT_ReadSerializedStore(void *handle
,
613 read_serialized_func read_func
, HCERTSTORE store
)
615 BYTE fileHeaderBuf
[sizeof(fileHeader
)];
619 /* Failure reading is non-critical, we'll leave the store empty */
620 ret
= read_func(handle
, fileHeaderBuf
, sizeof(fileHeaderBuf
), &read
);
624 ; /* an empty file is okay */
625 else if (read
!= sizeof(fileHeaderBuf
))
627 else if (!memcmp(fileHeaderBuf
, fileHeader
, read
))
629 WINE_CERT_PROP_HEADER propHdr
;
630 const void *context
= NULL
;
631 const WINE_CONTEXT_INTERFACE
*contextInterface
= NULL
;
636 ret
= read_func(handle
, &propHdr
, sizeof(propHdr
), &read
);
637 if (ret
&& read
== sizeof(propHdr
))
639 if (contextInterface
&& context
&&
640 (propHdr
.propID
== CERT_CERT_PROP_ID
||
641 propHdr
.propID
== CERT_CRL_PROP_ID
||
642 propHdr
.propID
== CERT_CTL_PROP_ID
))
644 /* We have a new context, so free the existing one */
645 Context_Release(context_from_ptr(context
));
647 if (propHdr
.cb
> bufSize
)
649 /* Not reusing realloc, because the old data aren't
653 buf
= CryptMemAlloc(propHdr
.cb
);
654 bufSize
= propHdr
.cb
;
657 ; /* Property is empty, nothing to do */
660 ret
= read_func(handle
, buf
, propHdr
.cb
, &read
);
661 if (ret
&& read
== propHdr
.cb
)
663 if (propHdr
.propID
== CERT_CERT_PROP_ID
)
665 contextInterface
= pCertInterface
;
666 ret
= contextInterface
->addEncodedToStore(store
,
667 X509_ASN_ENCODING
, buf
, read
,
668 CERT_STORE_ADD_NEW
, &context
);
670 else if (propHdr
.propID
== CERT_CRL_PROP_ID
)
672 contextInterface
= pCRLInterface
;
673 ret
= contextInterface
->addEncodedToStore(store
,
674 X509_ASN_ENCODING
, buf
, read
,
675 CERT_STORE_ADD_NEW
, &context
);
677 else if (propHdr
.propID
== CERT_CTL_PROP_ID
)
679 contextInterface
= pCTLInterface
;
680 ret
= contextInterface
->addEncodedToStore(store
,
681 X509_ASN_ENCODING
, buf
, read
,
682 CERT_STORE_ADD_NEW
, &context
);
686 if (!contextInterface
)
688 WARN("prop id %ld before a context id\n",
693 ret
= CRYPT_ReadContextProp(
694 contextInterface
, context
, &propHdr
, buf
,
702 } while (ret
&& read
> 0 && propHdr
.cb
);
703 if (contextInterface
&& context
)
705 /* Free the last context added */
706 Context_Release(context_from_ptr(context
));
719 static BOOL
read_file_wrapper(void *handle
, void *buffer
, DWORD bytesToRead
,
722 return ReadFile(handle
, buffer
, bytesToRead
, bytesRead
, NULL
);
725 BOOL
CRYPT_ReadSerializedStoreFromFile(HANDLE file
, HCERTSTORE store
)
727 return CRYPT_ReadSerializedStore(file
, read_file_wrapper
, store
);
732 const CRYPT_DATA_BLOB
*blob
;
736 static BOOL
read_blob_wrapper(void *handle
, void *buffer
, DWORD bytesToRead
,
739 struct BlobReader
*reader
= handle
;
742 if (reader
->current
< reader
->blob
->cbData
)
744 *bytesRead
= min(bytesToRead
, reader
->blob
->cbData
- reader
->current
);
745 memcpy(buffer
, reader
->blob
->pbData
+ reader
->current
, *bytesRead
);
746 reader
->current
+= *bytesRead
;
749 else if (reader
->current
== reader
->blob
->cbData
)
759 BOOL
CRYPT_ReadSerializedStoreFromBlob(const CRYPT_DATA_BLOB
*blob
,
762 struct BlobReader reader
= { blob
, 0 };
764 return CRYPT_ReadSerializedStore(&reader
, read_blob_wrapper
, store
);
767 static BOOL WINAPI
CRYPT_SerializeCertNoHash(PCCERT_CONTEXT pCertContext
,
768 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
770 return CRYPT_SerializeStoreElement(pCertContext
,
771 pCertContext
->pbCertEncoded
, pCertContext
->cbCertEncoded
,
772 CERT_CERT_PROP_ID
, pCertInterface
, dwFlags
, TRUE
, pbElement
, pcbElement
);
775 static BOOL WINAPI
CRYPT_SerializeCRLNoHash(PCCRL_CONTEXT pCrlContext
,
776 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
778 return CRYPT_SerializeStoreElement(pCrlContext
,
779 pCrlContext
->pbCrlEncoded
, pCrlContext
->cbCrlEncoded
,
780 CERT_CRL_PROP_ID
, pCRLInterface
, dwFlags
, TRUE
, pbElement
, pcbElement
);
783 static BOOL WINAPI
CRYPT_SerializeCTLNoHash(PCCTL_CONTEXT pCtlContext
,
784 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
786 return CRYPT_SerializeStoreElement(pCtlContext
,
787 pCtlContext
->pbCtlEncoded
, pCtlContext
->cbCtlEncoded
,
788 CERT_CTL_PROP_ID
, pCTLInterface
, dwFlags
, TRUE
, pbElement
, pcbElement
);
791 typedef BOOL (*SerializedOutputFunc
)(void *handle
, const void *buffer
,
794 static BOOL
CRYPT_SerializeContextsToStream(SerializedOutputFunc output
,
795 void *handle
, const WINE_CONTEXT_INTERFACE
*contextInterface
, HCERTSTORE store
)
797 const void *context
= NULL
;
801 context
= contextInterface
->enumContextsInStore(store
, context
);
807 ret
= contextInterface
->serialize(context
, 0, NULL
, &size
);
809 buf
= CryptMemAlloc(size
);
812 ret
= contextInterface
->serialize(context
, 0, buf
, &size
);
814 ret
= output(handle
, buf
, size
);
820 } while (ret
&& context
!= NULL
);
822 Context_Release(context_from_ptr(context
));
826 static BOOL
CRYPT_WriteSerializedStoreToStream(HCERTSTORE store
,
827 SerializedOutputFunc output
, void *handle
)
829 static const BYTE fileTrailer
[12] = { 0 };
830 WINE_CONTEXT_INTERFACE interface
;
833 ret
= output(handle
, fileHeader
, sizeof(fileHeader
));
836 interface
= *pCertInterface
;
837 interface
.serialize
= (SerializeElementFunc
)CRYPT_SerializeCertNoHash
;
838 ret
= CRYPT_SerializeContextsToStream(output
, handle
, &interface
,
843 interface
= *pCRLInterface
;
844 interface
.serialize
= (SerializeElementFunc
)CRYPT_SerializeCRLNoHash
;
845 ret
= CRYPT_SerializeContextsToStream(output
, handle
, &interface
,
850 interface
= *pCTLInterface
;
851 interface
.serialize
= (SerializeElementFunc
)CRYPT_SerializeCTLNoHash
;
852 ret
= CRYPT_SerializeContextsToStream(output
, handle
, &interface
,
856 ret
= output(handle
, fileTrailer
, sizeof(fileTrailer
));
860 static BOOL
CRYPT_FileOutputFunc(void *handle
, const void *buffer
, DWORD size
)
862 return WriteFile(handle
, buffer
, size
, &size
, NULL
);
865 static BOOL
CRYPT_WriteSerializedStoreToFile(HANDLE file
, HCERTSTORE store
)
867 SetFilePointer(file
, 0, NULL
, FILE_BEGIN
);
868 return CRYPT_WriteSerializedStoreToStream(store
, CRYPT_FileOutputFunc
,
872 static BOOL
CRYPT_SavePKCSToMem(HCERTSTORE store
,
873 DWORD dwMsgAndCertEncodingType
, void *handle
)
875 CERT_BLOB
*blob
= handle
;
876 CRYPT_SIGNED_INFO signedInfo
= { 0 };
877 PCCERT_CONTEXT cert
= NULL
;
878 PCCRL_CONTEXT crl
= NULL
;
882 TRACE("(%ld, %p)\n", blob
->pbData
? blob
->cbData
: 0, blob
->pbData
);
885 cert
= CertEnumCertificatesInStore(store
, cert
);
887 signedInfo
.cCertEncoded
++;
889 if (signedInfo
.cCertEncoded
)
891 signedInfo
.rgCertEncoded
= CryptMemAlloc(
892 signedInfo
.cCertEncoded
* sizeof(CERT_BLOB
));
893 if (!signedInfo
.rgCertEncoded
)
895 SetLastError(ERROR_OUTOFMEMORY
);
903 cert
= CertEnumCertificatesInStore(store
, cert
);
906 signedInfo
.rgCertEncoded
[i
].cbData
= cert
->cbCertEncoded
;
907 signedInfo
.rgCertEncoded
[i
].pbData
= cert
->pbCertEncoded
;
915 crl
= CertEnumCRLsInStore(store
, crl
);
917 signedInfo
.cCrlEncoded
++;
919 if (signedInfo
.cCrlEncoded
)
921 signedInfo
.rgCrlEncoded
= CryptMemAlloc(
922 signedInfo
.cCrlEncoded
* sizeof(CERT_BLOB
));
923 if (!signedInfo
.rgCrlEncoded
)
925 SetLastError(ERROR_OUTOFMEMORY
);
933 crl
= CertEnumCRLsInStore(store
, crl
);
936 signedInfo
.rgCrlEncoded
[i
].cbData
= crl
->cbCrlEncoded
;
937 signedInfo
.rgCrlEncoded
[i
].pbData
= crl
->pbCrlEncoded
;
945 ret
= CRYPT_AsnEncodeCMSSignedInfo(&signedInfo
, NULL
, &size
);
950 else if (blob
->cbData
< size
)
953 SetLastError(ERROR_MORE_DATA
);
959 ret
= CRYPT_AsnEncodeCMSSignedInfo(&signedInfo
, blob
->pbData
,
964 CryptMemFree(signedInfo
.rgCertEncoded
);
965 CryptMemFree(signedInfo
.rgCrlEncoded
);
966 TRACE("returning %d\n", ret
);
970 static BOOL
CRYPT_SavePKCSToFile(HCERTSTORE store
,
971 DWORD dwMsgAndCertEncodingType
, void *handle
)
973 CERT_BLOB blob
= { 0, NULL
};
976 TRACE("(%p)\n", handle
);
978 ret
= CRYPT_SavePKCSToMem(store
, dwMsgAndCertEncodingType
, &blob
);
981 blob
.pbData
= CryptMemAlloc(blob
.cbData
);
984 ret
= CRYPT_SavePKCSToMem(store
, dwMsgAndCertEncodingType
, &blob
);
986 ret
= WriteFile(handle
, blob
.pbData
, blob
.cbData
,
991 SetLastError(ERROR_OUTOFMEMORY
);
995 TRACE("returning %d\n", ret
);
999 static BOOL
CRYPT_SaveSerializedToFile(HCERTSTORE store
,
1000 DWORD dwMsgAndCertEncodingType
, void *handle
)
1002 return CRYPT_WriteSerializedStoreToFile(handle
, store
);
1005 struct MemWrittenTracker
1012 /* handle is a pointer to a MemWrittenTracker. Assumes its pointer is valid. */
1013 static BOOL
CRYPT_MemOutputFunc(void *handle
, const void *buffer
, DWORD size
)
1015 struct MemWrittenTracker
*tracker
= handle
;
1018 if (tracker
->written
+ size
> tracker
->cbData
)
1020 SetLastError(ERROR_MORE_DATA
);
1021 /* Update written so caller can notify its caller of the required size
1023 tracker
->written
+= size
;
1028 memcpy(tracker
->pbData
+ tracker
->written
, buffer
, size
);
1029 tracker
->written
+= size
;
1035 static BOOL
CRYPT_CountSerializedBytes(void *handle
, const void *buffer
,
1038 *(DWORD
*)handle
+= size
;
1042 static BOOL
CRYPT_SaveSerializedToMem(HCERTSTORE store
,
1043 DWORD dwMsgAndCertEncodingType
, void *handle
)
1045 CERT_BLOB
*blob
= handle
;
1049 ret
= CRYPT_WriteSerializedStoreToStream(store
, CRYPT_CountSerializedBytes
,
1054 blob
->cbData
= size
;
1055 else if (blob
->cbData
< size
)
1057 SetLastError(ERROR_MORE_DATA
);
1058 blob
->cbData
= size
;
1063 struct MemWrittenTracker tracker
= { blob
->cbData
, blob
->pbData
,
1066 ret
= CRYPT_WriteSerializedStoreToStream(store
, CRYPT_MemOutputFunc
,
1068 if (!ret
&& GetLastError() == ERROR_MORE_DATA
)
1069 blob
->cbData
= tracker
.written
;
1072 TRACE("returning %d\n", ret
);
1076 BOOL WINAPI
CertSaveStore(HCERTSTORE hCertStore
, DWORD dwMsgAndCertEncodingType
,
1077 DWORD dwSaveAs
, DWORD dwSaveTo
, void *pvSaveToPara
, DWORD dwFlags
)
1079 BOOL (*saveFunc
)(HCERTSTORE
, DWORD
, void *);
1081 BOOL ret
, closeFile
= TRUE
;
1083 TRACE("(%p, %08lx, %ld, %ld, %p, %08lx)\n", hCertStore
,
1084 dwMsgAndCertEncodingType
, dwSaveAs
, dwSaveTo
, pvSaveToPara
, dwFlags
);
1088 case CERT_STORE_SAVE_AS_STORE
:
1089 if (dwSaveTo
== CERT_STORE_SAVE_TO_MEMORY
)
1090 saveFunc
= CRYPT_SaveSerializedToMem
;
1092 saveFunc
= CRYPT_SaveSerializedToFile
;
1094 case CERT_STORE_SAVE_AS_PKCS7
:
1095 if (dwSaveTo
== CERT_STORE_SAVE_TO_MEMORY
)
1096 saveFunc
= CRYPT_SavePKCSToMem
;
1098 saveFunc
= CRYPT_SavePKCSToFile
;
1101 WARN("unimplemented for %ld\n", dwSaveAs
);
1102 SetLastError(ERROR_INVALID_PARAMETER
);
1107 case CERT_STORE_SAVE_TO_FILE
:
1108 handle
= pvSaveToPara
;
1111 case CERT_STORE_SAVE_TO_FILENAME_A
:
1112 handle
= CreateFileA(pvSaveToPara
, GENERIC_WRITE
, 0, NULL
,
1113 CREATE_ALWAYS
, 0, NULL
);
1115 case CERT_STORE_SAVE_TO_FILENAME_W
:
1116 handle
= CreateFileW(pvSaveToPara
, GENERIC_WRITE
, 0, NULL
,
1117 CREATE_ALWAYS
, 0, NULL
);
1119 case CERT_STORE_SAVE_TO_MEMORY
:
1120 handle
= pvSaveToPara
;
1123 WARN("unimplemented for %ld\n", dwSaveTo
);
1124 SetLastError(ERROR_INVALID_PARAMETER
);
1127 ret
= saveFunc(hCertStore
, dwMsgAndCertEncodingType
, handle
);
1129 CloseHandle(handle
);
1130 TRACE("returning %d\n", ret
);
1134 BOOL WINAPI
CertAddSerializedElementToStore(HCERTSTORE hCertStore
,
1135 const BYTE
*pbElement
, DWORD cbElement
, DWORD dwAddDisposition
, DWORD dwFlags
,
1136 DWORD dwContextTypeFlags
, DWORD
*pdwContentType
, const void **ppvContext
)
1138 const void *context
;
1142 TRACE("(%p, %p, %ld, %08lx, %08lx, %08lx, %p, %p)\n", hCertStore
,
1143 pbElement
, cbElement
, dwAddDisposition
, dwFlags
, dwContextTypeFlags
,
1144 pdwContentType
, ppvContext
);
1146 /* Call the internal function, then delete the hashes. Tests show this
1147 * function uses real hash values, not whatever's stored in the hash
1150 context
= CRYPT_ReadSerializedElement(pbElement
, cbElement
,
1151 dwContextTypeFlags
, &type
);
1154 const WINE_CONTEXT_INTERFACE
*contextInterface
= NULL
;
1158 case CERT_STORE_CERTIFICATE_CONTEXT
:
1159 contextInterface
= pCertInterface
;
1161 case CERT_STORE_CRL_CONTEXT
:
1162 contextInterface
= pCRLInterface
;
1164 case CERT_STORE_CTL_CONTEXT
:
1165 contextInterface
= pCTLInterface
;
1168 SetLastError(E_INVALIDARG
);
1170 if (contextInterface
)
1172 contextInterface
->setProp(context
, CERT_HASH_PROP_ID
, 0, NULL
);
1173 contextInterface
->setProp(context
, CERT_MD5_HASH_PROP_ID
, 0, NULL
);
1174 contextInterface
->setProp(context
, CERT_SIGNATURE_HASH_PROP_ID
, 0,
1177 *pdwContentType
= type
;
1178 ret
= contextInterface
->addContextToStore(hCertStore
, context
,
1179 dwAddDisposition
, ppvContext
);
1180 Context_Release(context_from_ptr(context
));