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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #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
, *PWINE_CERT_PROP_HEADER
;
39 BOOL WINAPI
CertSerializeCRLStoreElement(PCCRL_CONTEXT pCrlContext
,
40 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
42 FIXME("(%p, %08lx, %p, %p): stub\n", pCrlContext
, dwFlags
, pbElement
,
47 BOOL WINAPI
CertSerializeCTLStoreElement(PCCTL_CONTEXT pCtlContext
,
48 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
50 FIXME("(%p, %08lx, %p, %p): stub\n", pCtlContext
, dwFlags
, pbElement
,
55 BOOL WINAPI
CertSerializeCertificateStoreElement(PCCERT_CONTEXT pCertContext
,
56 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
60 TRACE("(%p, %08lx, %p, %p)\n", pCertContext
, dwFlags
, pbElement
,
65 DWORD bytesNeeded
= sizeof(WINE_CERT_PROP_HEADER
) +
66 pCertContext
->cbCertEncoded
;
71 prop
= CertEnumCertificateContextProperties(pCertContext
, prop
);
76 ret
= CertGetCertificateContextProperty(pCertContext
,
77 prop
, NULL
, &propSize
);
79 bytesNeeded
+= sizeof(WINE_CERT_PROP_HEADER
) + propSize
;
81 } while (ret
&& prop
!= 0);
85 *pcbElement
= bytesNeeded
;
88 else if (*pcbElement
< bytesNeeded
)
90 *pcbElement
= bytesNeeded
;
91 SetLastError(ERROR_MORE_DATA
);
96 PWINE_CERT_PROP_HEADER hdr
;
102 prop
= CertEnumCertificateContextProperties(pCertContext
, prop
);
107 ret
= CertGetCertificateContextProperty(pCertContext
,
108 prop
, NULL
, &propSize
);
111 if (bufSize
< propSize
)
114 buf
= CryptMemRealloc(buf
, propSize
);
116 buf
= CryptMemAlloc(propSize
);
121 ret
= CertGetCertificateContextProperty(
122 pCertContext
, prop
, buf
, &propSize
);
125 hdr
= (PWINE_CERT_PROP_HEADER
)pbElement
;
129 pbElement
+= sizeof(WINE_CERT_PROP_HEADER
);
132 memcpy(pbElement
, buf
, propSize
);
133 pbElement
+= propSize
;
141 } while (ret
&& prop
!= 0);
144 hdr
= (PWINE_CERT_PROP_HEADER
)pbElement
;
145 hdr
->propID
= CERT_CERT_PROP_ID
;
147 hdr
->cb
= pCertContext
->cbCertEncoded
;
148 memcpy(pbElement
+ sizeof(WINE_CERT_PROP_HEADER
),
149 pCertContext
->pbCertEncoded
, pCertContext
->cbCertEncoded
);
157 /* Looks for the property with ID propID in the buffer buf. Returns a pointer
158 * to its header if a valid header is found, NULL if not. Valid means the
159 * length of thte property won't overrun buf, and the unknown field is 1.
161 static const WINE_CERT_PROP_HEADER
*CRYPT_findPropID(const BYTE
*buf
,
162 DWORD size
, DWORD propID
)
164 const WINE_CERT_PROP_HEADER
*ret
= NULL
;
167 while (size
&& !ret
&& !done
)
169 if (size
< sizeof(WINE_CERT_PROP_HEADER
))
171 SetLastError(CRYPT_E_FILE_ERROR
);
176 const WINE_CERT_PROP_HEADER
*hdr
=
177 (const WINE_CERT_PROP_HEADER
*)buf
;
179 size
-= sizeof(WINE_CERT_PROP_HEADER
);
180 buf
+= sizeof(WINE_CERT_PROP_HEADER
);
183 SetLastError(E_INVALIDARG
);
186 else if (!hdr
->propID
)
188 /* assume a zero prop ID means the data are uninitialized, so
193 else if (hdr
->unknown
!= 1)
195 SetLastError(ERROR_FILE_NOT_FOUND
);
198 else if (hdr
->propID
== propID
)
210 const void *CRYPT_ReadSerializedElement(const BYTE
*pbElement
, DWORD cbElement
,
211 DWORD dwContextTypeFlags
, DWORD
*pdwContentType
)
215 TRACE("(%p, %ld, %08lx, %p)\n", pbElement
, cbElement
, dwContextTypeFlags
,
220 SetLastError(ERROR_END_OF_MEDIA
);
226 const WINE_CONTEXT_INTERFACE
*contextInterface
= NULL
;
227 const WINE_CERT_PROP_HEADER
*hdr
= NULL
;
233 if (dwContextTypeFlags
== CERT_STORE_ALL_CONTEXT_FLAG
)
235 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CERT_PROP_ID
);
237 type
= CERT_STORE_CERTIFICATE_CONTEXT
;
240 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CRL_PROP_ID
);
242 type
= CERT_STORE_CRL_CONTEXT
;
245 hdr
= CRYPT_findPropID(pbElement
, cbElement
,
248 type
= CERT_STORE_CTL_CONTEXT
;
252 else if (dwContextTypeFlags
& CERT_STORE_CERTIFICATE_CONTEXT_FLAG
)
254 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CERT_PROP_ID
);
255 type
= CERT_STORE_CERTIFICATE_CONTEXT
;
257 else if (dwContextTypeFlags
& CERT_STORE_CRL_CONTEXT_FLAG
)
259 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CRL_PROP_ID
);
260 type
= CERT_STORE_CRL_CONTEXT
;
262 else if (dwContextTypeFlags
& CERT_STORE_CTL_CONTEXT_FLAG
)
264 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CTL_PROP_ID
);
265 type
= CERT_STORE_CTL_CONTEXT
;
270 case CERT_STORE_CERTIFICATE_CONTEXT
:
271 contextInterface
= pCertInterface
;
273 case CERT_STORE_CRL_CONTEXT
:
274 contextInterface
= pCRLInterface
;
276 case CERT_STORE_CTL_CONTEXT
:
277 contextInterface
= pCTLInterface
;
280 SetLastError(E_INVALIDARG
);
287 context
= contextInterface
->create(X509_ASN_ENCODING
,
288 (BYTE
*)hdr
+ sizeof(WINE_CERT_PROP_HEADER
), hdr
->cb
);
291 BOOL noMoreProps
= FALSE
;
293 while (!noMoreProps
&& ret
)
295 if (cbElement
< sizeof(WINE_CERT_PROP_HEADER
))
299 const WINE_CERT_PROP_HEADER
*hdr
=
300 (const WINE_CERT_PROP_HEADER
*)pbElement
;
302 TRACE("prop is %ld\n", hdr
->propID
);
303 cbElement
-= sizeof(WINE_CERT_PROP_HEADER
);
304 pbElement
+= sizeof(WINE_CERT_PROP_HEADER
);
305 if (cbElement
< hdr
->cb
)
307 SetLastError(E_INVALIDARG
);
310 else if (!hdr
->propID
)
312 /* Like in CRYPT_findPropID, stop if the propID is zero
316 else if (hdr
->unknown
!= 1)
318 SetLastError(ERROR_FILE_NOT_FOUND
);
321 else if (hdr
->propID
!= CERT_CERT_PROP_ID
&&
322 hdr
->propID
!= CERT_CRL_PROP_ID
&& hdr
->propID
!=
325 /* Have to create a blob for most types, but not
330 case CERT_AUTO_ENROLL_PROP_ID
:
331 case CERT_CTL_USAGE_PROP_ID
:
332 case CERT_DESCRIPTION_PROP_ID
:
333 case CERT_FRIENDLY_NAME_PROP_ID
:
334 case CERT_HASH_PROP_ID
:
335 case CERT_KEY_IDENTIFIER_PROP_ID
:
336 case CERT_MD5_HASH_PROP_ID
:
337 case CERT_NEXT_UPDATE_LOCATION_PROP_ID
:
338 case CERT_PUBKEY_ALG_PARA_PROP_ID
:
339 case CERT_PVK_FILE_PROP_ID
:
340 case CERT_SIGNATURE_HASH_PROP_ID
:
341 case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID
:
342 case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID
:
343 case CERT_ENROLLMENT_PROP_ID
:
344 case CERT_CROSS_CERT_DIST_POINTS_PROP_ID
:
345 case CERT_RENEWAL_PROP_ID
:
347 CRYPT_DATA_BLOB blob
= { hdr
->cb
,
350 ret
= contextInterface
->setProp(context
,
351 hdr
->propID
, 0, &blob
);
354 case CERT_DATE_STAMP_PROP_ID
:
355 ret
= contextInterface
->setProp(context
,
356 hdr
->propID
, 0, pbElement
);
359 FIXME("prop ID %ld: stub\n", hdr
->propID
);
362 pbElement
+= hdr
->cb
;
363 cbElement
-= hdr
->cb
;
371 *pdwContentType
= type
;
375 contextInterface
->free(context
);
382 SetLastError(STATUS_ACCESS_VIOLATION
);
389 BOOL WINAPI
CertAddSerializedElementToStore(HCERTSTORE hCertStore
,
390 const BYTE
*pbElement
, DWORD cbElement
, DWORD dwAddDisposition
, DWORD dwFlags
,
391 DWORD dwContextTypeFlags
, DWORD
*pdwContentType
, const void **ppvContext
)
397 TRACE("(%p, %p, %ld, %08lx, %08lx, %08lx, %p, %p)\n", hCertStore
,
398 pbElement
, cbElement
, dwAddDisposition
, dwFlags
, dwContextTypeFlags
,
399 pdwContentType
, ppvContext
);
401 /* Call the internal function, then delete the hashes. Tests show this
402 * function uses real hash values, not whatever's stored in the hash
405 context
= CRYPT_ReadSerializedElement(pbElement
, cbElement
,
406 dwContextTypeFlags
, &type
);
409 const WINE_CONTEXT_INTERFACE
*contextInterface
= NULL
;
413 case CERT_STORE_CERTIFICATE_CONTEXT
:
414 contextInterface
= pCertInterface
;
416 case CERT_STORE_CRL_CONTEXT
:
417 contextInterface
= pCRLInterface
;
419 case CERT_STORE_CTL_CONTEXT
:
420 contextInterface
= pCTLInterface
;
423 SetLastError(E_INVALIDARG
);
425 if (contextInterface
)
427 contextInterface
->setProp(context
, CERT_HASH_PROP_ID
, 0, NULL
);
428 contextInterface
->setProp(context
, CERT_MD5_HASH_PROP_ID
, 0, NULL
);
429 contextInterface
->setProp(context
, CERT_SIGNATURE_HASH_PROP_ID
, 0,
432 *pdwContentType
= type
;
433 ret
= contextInterface
->addContextToStore(hCertStore
, context
,
434 dwAddDisposition
, ppvContext
);
435 contextInterface
->free(context
);