2 * Copyright 2008 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 #define NONAMELESSUNION
27 #include "wine/debug.h"
28 #include "crypt32_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
32 BOOL WINAPI
CertAddEncodedCTLToStore(HCERTSTORE hCertStore
,
33 DWORD dwMsgAndCertEncodingType
, const BYTE
*pbCtlEncoded
, DWORD cbCtlEncoded
,
34 DWORD dwAddDisposition
, PCCTL_CONTEXT
*ppCtlContext
)
36 PCCTL_CONTEXT ctl
= CertCreateCTLContext(dwMsgAndCertEncodingType
,
37 pbCtlEncoded
, cbCtlEncoded
);
40 TRACE("(%p, %08x, %p, %d, %08x, %p)\n", hCertStore
,
41 dwMsgAndCertEncodingType
, pbCtlEncoded
, cbCtlEncoded
, dwAddDisposition
,
46 ret
= CertAddCTLContextToStore(hCertStore
, ctl
, dwAddDisposition
,
48 CertFreeCTLContext(ctl
);
55 PCCTL_CONTEXT WINAPI
CertEnumCTLsInStore(HCERTSTORE hCertStore
,
58 WINECRYPT_CERTSTORE
*hcs
= (WINECRYPT_CERTSTORE
*)hCertStore
;
61 TRACE("(%p, %p)\n", hCertStore
, pPrev
);
64 else if (hcs
->dwMagic
!= WINE_CRYPTCERTSTORE_MAGIC
)
67 ret
= (PCCTL_CONTEXT
)hcs
->ctls
.enumContext(hcs
, (void *)pPrev
);
71 BOOL WINAPI
CertDeleteCTLFromStore(PCCTL_CONTEXT pCtlContext
)
75 TRACE("(%p)\n", pCtlContext
);
79 else if (!pCtlContext
->hCertStore
)
82 CertFreeCTLContext(pCtlContext
);
86 PWINECRYPT_CERTSTORE hcs
=
87 (PWINECRYPT_CERTSTORE
)pCtlContext
->hCertStore
;
89 if (hcs
->dwMagic
!= WINE_CRYPTCERTSTORE_MAGIC
)
92 ret
= hcs
->ctls
.deleteContext(hcs
, (void *)pCtlContext
);
93 CertFreeCTLContext(pCtlContext
);
98 PCCTL_CONTEXT WINAPI
CertCreateCTLContext(DWORD dwMsgAndCertEncodingType
,
99 const BYTE
*pbCtlEncoded
, DWORD cbCtlEncoded
)
101 PCTL_CONTEXT ctl
= NULL
;
104 BYTE
*content
= NULL
;
105 DWORD contentSize
= 0, size
;
106 PCTL_INFO ctlInfo
= NULL
;
108 TRACE("(%08x, %p, %d)\n", dwMsgAndCertEncodingType
, pbCtlEncoded
,
111 if (GET_CERT_ENCODING_TYPE(dwMsgAndCertEncodingType
) != X509_ASN_ENCODING
)
113 SetLastError(E_INVALIDARG
);
116 if (!pbCtlEncoded
|| !cbCtlEncoded
)
118 SetLastError(ERROR_INVALID_DATA
);
121 msg
= CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING
| X509_ASN_ENCODING
, 0, 0,
125 ret
= CryptMsgUpdate(msg
, pbCtlEncoded
, cbCtlEncoded
, TRUE
);
128 SetLastError(ERROR_INVALID_DATA
);
131 /* Check that it's really a CTL */
132 ret
= CryptMsgGetParam(msg
, CMSG_INNER_CONTENT_TYPE_PARAM
, 0, NULL
, &size
);
135 char *innerContent
= CryptMemAlloc(size
);
139 ret
= CryptMsgGetParam(msg
, CMSG_INNER_CONTENT_TYPE_PARAM
, 0,
140 innerContent
, &size
);
143 if (strcmp(innerContent
, szOID_CTL
))
145 SetLastError(ERROR_INVALID_DATA
);
149 CryptMemFree(innerContent
);
153 SetLastError(ERROR_OUTOFMEMORY
);
159 ret
= CryptMsgGetParam(msg
, CMSG_CONTENT_PARAM
, 0, NULL
, &contentSize
);
162 content
= CryptMemAlloc(contentSize
);
165 ret
= CryptMsgGetParam(msg
, CMSG_CONTENT_PARAM
, 0, content
,
169 ret
= CryptDecodeObjectEx(dwMsgAndCertEncodingType
, PKCS_CTL
,
170 content
, contentSize
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
171 (BYTE
*)&ctlInfo
, &size
);
174 ctl
= (PCTL_CONTEXT
)Context_CreateDataContext(
175 sizeof(CTL_CONTEXT
));
178 BYTE
*data
= CryptMemAlloc(cbCtlEncoded
);
182 memcpy(data
, pbCtlEncoded
, cbCtlEncoded
);
183 ctl
->dwMsgAndCertEncodingType
=
184 X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
;
185 ctl
->pbCtlEncoded
= data
;
186 ctl
->cbCtlEncoded
= cbCtlEncoded
;
187 ctl
->pCtlInfo
= ctlInfo
;
188 ctl
->hCertStore
= NULL
;
189 ctl
->hCryptMsg
= msg
;
190 ctl
->pbCtlContext
= content
;
191 ctl
->cbCtlContext
= contentSize
;
195 SetLastError(ERROR_OUTOFMEMORY
);
201 SetLastError(ERROR_OUTOFMEMORY
);
209 SetLastError(ERROR_OUTOFMEMORY
);
219 CryptMemFree(content
);
222 return (PCCTL_CONTEXT
)ctl
;
225 PCCTL_CONTEXT WINAPI
CertDuplicateCTLContext(PCCTL_CONTEXT pCtlContext
)
227 TRACE("(%p)\n", pCtlContext
);
228 Context_AddRef((void *)pCtlContext
, sizeof(CTL_CONTEXT
));
232 static void CTLDataContext_Free(void *context
)
234 PCTL_CONTEXT ctlContext
= (PCTL_CONTEXT
)context
;
236 CryptMsgClose(ctlContext
->hCryptMsg
);
237 CryptMemFree(ctlContext
->pbCtlEncoded
);
238 CryptMemFree(ctlContext
->pbCtlContext
);
239 LocalFree(ctlContext
->pCtlInfo
);
242 BOOL WINAPI
CertFreeCTLContext(PCCTL_CONTEXT pCTLContext
)
244 TRACE("(%p)\n", pCTLContext
);
247 Context_Release((void *)pCTLContext
, sizeof(CTL_CONTEXT
),
248 CTLDataContext_Free
);
252 DWORD WINAPI
CertEnumCTLContextProperties(PCCTL_CONTEXT pCTLContext
,
255 PCONTEXT_PROPERTY_LIST properties
= Context_GetProperties(
256 (void *)pCTLContext
, sizeof(CTL_CONTEXT
));
259 TRACE("(%p, %d)\n", pCTLContext
, dwPropId
);
262 ret
= ContextPropertyList_EnumPropIDs(properties
, dwPropId
);
268 static BOOL
CTLContext_SetProperty(PCCTL_CONTEXT context
, DWORD dwPropId
,
269 DWORD dwFlags
, const void *pvData
);
271 static BOOL
CTLContext_GetHashProp(PCCTL_CONTEXT context
, DWORD dwPropId
,
272 ALG_ID algID
, const BYTE
*toHash
, DWORD toHashLen
, void *pvData
,
275 BOOL ret
= CryptHashCertificate(0, algID
, 0, toHash
, toHashLen
, pvData
,
279 CRYPT_DATA_BLOB blob
= { *pcbData
, pvData
};
281 ret
= CTLContext_SetProperty(context
, dwPropId
, 0, &blob
);
286 static BOOL
CTLContext_GetProperty(PCCTL_CONTEXT context
, DWORD dwPropId
,
287 void *pvData
, DWORD
*pcbData
)
289 PCONTEXT_PROPERTY_LIST properties
=
290 Context_GetProperties(context
, sizeof(CTL_CONTEXT
));
292 CRYPT_DATA_BLOB blob
;
294 TRACE("(%p, %d, %p, %p)\n", context
, dwPropId
, pvData
, pcbData
);
297 ret
= ContextPropertyList_FindProperty(properties
, dwPropId
, &blob
);
303 *pcbData
= blob
.cbData
;
304 else if (*pcbData
< blob
.cbData
)
306 SetLastError(ERROR_MORE_DATA
);
307 *pcbData
= blob
.cbData
;
312 memcpy(pvData
, blob
.pbData
, blob
.cbData
);
313 *pcbData
= blob
.cbData
;
318 /* Implicit properties */
321 case CERT_SHA1_HASH_PROP_ID
:
322 ret
= CTLContext_GetHashProp(context
, dwPropId
, CALG_SHA1
,
323 context
->pbCtlEncoded
, context
->cbCtlEncoded
, pvData
, pcbData
);
325 case CERT_MD5_HASH_PROP_ID
:
326 ret
= CTLContext_GetHashProp(context
, dwPropId
, CALG_MD5
,
327 context
->pbCtlEncoded
, context
->cbCtlEncoded
, pvData
, pcbData
);
330 SetLastError(CRYPT_E_NOT_FOUND
);
333 TRACE("returning %d\n", ret
);
337 BOOL WINAPI
CertGetCTLContextProperty(PCCTL_CONTEXT pCTLContext
,
338 DWORD dwPropId
, void *pvData
, DWORD
*pcbData
)
342 TRACE("(%p, %d, %p, %p)\n", pCTLContext
, dwPropId
, pvData
, pcbData
);
347 case CERT_CERT_PROP_ID
:
348 case CERT_CRL_PROP_ID
:
349 case CERT_CTL_PROP_ID
:
350 SetLastError(E_INVALIDARG
);
353 case CERT_ACCESS_STATE_PROP_ID
:
356 *pcbData
= sizeof(DWORD
);
359 else if (*pcbData
< sizeof(DWORD
))
361 SetLastError(ERROR_MORE_DATA
);
362 *pcbData
= sizeof(DWORD
);
367 if (pCTLContext
->hCertStore
)
368 ret
= CertGetStoreProperty(pCTLContext
->hCertStore
, dwPropId
,
371 *(DWORD
*)pvData
= 0;
376 ret
= CTLContext_GetProperty(pCTLContext
, dwPropId
, pvData
,
382 static BOOL
CTLContext_SetProperty(PCCTL_CONTEXT context
, DWORD dwPropId
,
383 DWORD dwFlags
, const void *pvData
)
385 PCONTEXT_PROPERTY_LIST properties
=
386 Context_GetProperties(context
, sizeof(CTL_CONTEXT
));
389 TRACE("(%p, %d, %08x, %p)\n", context
, dwPropId
, dwFlags
, pvData
);
395 ContextPropertyList_RemoveProperty(properties
, dwPropId
);
402 case CERT_AUTO_ENROLL_PROP_ID
:
403 case CERT_CTL_USAGE_PROP_ID
: /* same as CERT_ENHKEY_USAGE_PROP_ID */
404 case CERT_DESCRIPTION_PROP_ID
:
405 case CERT_FRIENDLY_NAME_PROP_ID
:
406 case CERT_HASH_PROP_ID
:
407 case CERT_KEY_IDENTIFIER_PROP_ID
:
408 case CERT_MD5_HASH_PROP_ID
:
409 case CERT_NEXT_UPDATE_LOCATION_PROP_ID
:
410 case CERT_PUBKEY_ALG_PARA_PROP_ID
:
411 case CERT_PVK_FILE_PROP_ID
:
412 case CERT_SIGNATURE_HASH_PROP_ID
:
413 case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID
:
414 case CERT_SUBJECT_NAME_MD5_HASH_PROP_ID
:
415 case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID
:
416 case CERT_ENROLLMENT_PROP_ID
:
417 case CERT_CROSS_CERT_DIST_POINTS_PROP_ID
:
418 case CERT_RENEWAL_PROP_ID
:
420 PCRYPT_DATA_BLOB blob
= (PCRYPT_DATA_BLOB
)pvData
;
422 ret
= ContextPropertyList_SetProperty(properties
, dwPropId
,
423 blob
->pbData
, blob
->cbData
);
426 case CERT_DATE_STAMP_PROP_ID
:
427 ret
= ContextPropertyList_SetProperty(properties
, dwPropId
,
428 (const BYTE
*)pvData
, sizeof(FILETIME
));
431 FIXME("%d: stub\n", dwPropId
);
435 TRACE("returning %d\n", ret
);
439 BOOL WINAPI
CertSetCTLContextProperty(PCCTL_CONTEXT pCTLContext
,
440 DWORD dwPropId
, DWORD dwFlags
, const void *pvData
)
444 TRACE("(%p, %d, %08x, %p)\n", pCTLContext
, dwPropId
, dwFlags
, pvData
);
446 /* Handle special cases for "read-only"/invalid prop IDs. Windows just
447 * crashes on most of these, I'll be safer.
452 case CERT_ACCESS_STATE_PROP_ID
:
453 case CERT_CERT_PROP_ID
:
454 case CERT_CRL_PROP_ID
:
455 case CERT_CTL_PROP_ID
:
456 SetLastError(E_INVALIDARG
);
459 ret
= CTLContext_SetProperty(pCTLContext
, dwPropId
, dwFlags
, pvData
);
460 TRACE("returning %d\n", ret
);