Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
8d1cf4eb
Commit
8d1cf4eb
authored
Aug 29, 2005
by
Juan Lang
Committed by
Alexandre Julliard
Aug 29, 2005
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implemented memory cert stores.
parent
682dd707
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
1435 additions
and
92 deletions
+1435
-92
cert.c
dlls/crypt32/cert.c
+1133
-92
cert.c
dlls/crypt32/tests/cert.c
+302
-0
No files found.
dlls/crypt32/cert.c
View file @
8d1cf4eb
...
...
@@ -15,6 +15,17 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* FIXME:
* - As you can see in the stubs below, support for CRLs and CTLs is missing.
* Mostly this should be copy-paste work, and some code (e.g. extended
* properties) could be shared between them.
* - Opening a cert store provider should be morphed to support loading
* external DLLs.
* - The concept of physical stores and locations isn't implemented. (This
* doesn't mean registry stores et al aren't implemented. See the PSDK for
* registering and enumerating physical stores and locations.)
* - Many flags, options and whatnot are unimplemented.
*/
#include <stdarg.h>
#include "windef.h"
...
...
@@ -22,55 +33,520 @@
#include "winreg.h"
#include "wincrypt.h"
#include "wine/debug.h"
#include "wine/list.h"
#include "crypt32_private.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
crypt
);
#define WINE_CRYPTCERTSTORE_MAGIC 0x74726563
/* The following aren't defined in wincrypt.h, as they're "reserved" */
#define CERT_CERT_PROP_ID 32
#define CERT_CRL_PROP_ID 33
#define CERT_CTL_PROP_ID 34
struct
WINE_CRYPTCERTSTORE
;
typedef
struct
WINE_CRYPTCERTSTORE
*
(
*
StoreOpenFunc
)(
HCRYPTPROV
hCryptProv
,
DWORD
dwFlags
,
const
void
*
pvPara
);
struct
_WINE_CERT_CONTEXT_REF
;
/* Called to enumerate the next certificate in a store. The returned pointer
* must be newly allocated (via HeapAlloc): CertFreeCertificateContext frees
* it.
*/
typedef
struct
_WINE_CERT_CONTEXT_REF
*
(
*
EnumCertFunc
)
(
struct
WINE_CRYPTCERTSTORE
*
store
,
struct
_WINE_CERT_CONTEXT_REF
*
pPrev
);
struct
_WINE_CERT_CONTEXT
;
/* Called to create a new reference to an existing cert context. Should call
* CRYPT_InitCertRef to make sure the reference count is properly updated.
* If the store does not provide any additional allocated data (that is, does
* not need to implement a FreeCertFunc), it may use CRYPT_CreateCertRef for
* this.
*/
typedef
struct
_WINE_CERT_CONTEXT_REF
*
(
*
CreateRefFunc
)
(
struct
_WINE_CERT_CONTEXT
*
context
,
HCERTSTORE
store
);
/* Optional, called when a cert context reference is being freed. Don't free
* the ref pointer itself, CertFreeCertificateContext does that.
*/
typedef
void
(
*
FreeCertFunc
)(
struct
_WINE_CERT_CONTEXT_REF
*
ref
);
typedef
enum
_CertStoreType
{
StoreTypeMem
,
StoreTypeCollection
,
StoreTypeReg
,
StoreTypeDummy
,
}
CertStoreType
;
/* A cert store is polymorphic through the use of function pointers. A type
* is still needed to distinguish collection stores from other types.
* On the function pointers:
* - closeStore is called when the store's ref count becomes 0
* - addCert is called with a PWINE_CERT_CONTEXT as the second parameter
* - control is optional, but should be implemented by any store that supports
* persistence
*/
typedef
struct
WINE_CRYPTCERTSTORE
{
DWORD
dwMagic
;
}
WINECRYPT_CERTSTORE
;
DWORD
dwMagic
;
LONG
ref
;
DWORD
dwOpenFlags
;
HCRYPTPROV
cryptProv
;
CertStoreType
type
;
PFN_CERT_STORE_PROV_CLOSE
closeStore
;
PFN_CERT_STORE_PROV_WRITE_CERT
addCert
;
CreateRefFunc
createCertRef
;
EnumCertFunc
enumCert
;
PFN_CERT_STORE_PROV_DELETE_CERT
deleteCert
;
FreeCertFunc
freeCert
;
/* optional */
PFN_CERT_STORE_PROV_CONTROL
control
;
/* optional */
}
WINECRYPT_CERTSTORE
,
*
PWINECRYPT_CERTSTORE
;
/* A certificate context has pointers to data that are owned by this module,
* so rather than duplicate the data every time a certificate context is
* copied, I keep a reference count to the data. Thus I have two data
* structures, the "true" certificate context (that has the reference count)
* and a reference certificate context, that has a pointer to the true context.
* Each one can be cast to a PCERT_CONTEXT, though you'll usually be dealing
* with the reference version.
*/
typedef
struct
_WINE_CERT_CONTEXT
{
CERT_CONTEXT
cert
;
LONG
ref
;
CRITICAL_SECTION
cs
;
struct
list
extendedProperties
;
}
WINE_CERT_CONTEXT
,
*
PWINE_CERT_CONTEXT
;
typedef
struct
_WINE_CERT_CONTEXT_REF
{
CERT_CONTEXT
cert
;
WINE_CERT_CONTEXT
*
context
;
}
WINE_CERT_CONTEXT_REF
,
*
PWINE_CERT_CONTEXT_REF
;
/*
* CertOpenStore
*
* System Store CA is
* HKLM\\Software\\Microsoft\\SystemCertificates\\CA\\
* Certificates\\<compressed guid>
* "Blob" = REG_BINARY
* CRLs\\<compressed guid>
* "Blob" = REG_BINARY
* CTLs\\<compressed guid>
* "Blob" = REG_BINARY
/* An extended certificate property in serialized form is prefixed by this
* header.
*/
HCERTSTORE
WINAPI
CertOpenStore
(
LPCSTR
lpszStoreProvider
,
DWORD
dwMsgAndCertEncodingType
,
HCRYPTPROV
hCryptProv
,
DWORD
dwFlags
,
const
void
*
pvPara
)
typedef
struct
_WINE_CERT_PROP_HEADER
{
WINECRYPT_CERTSTORE
*
hcs
;
DWORD
propID
;
DWORD
unknown
;
/* always 1 */
DWORD
cb
;
}
WINE_CERT_PROP_HEADER
,
*
PWINE_CERT_PROP_HEADER
;
FIXME
(
"%s %08lx %08lx %08lx %p stub
\n
"
,
debugstr_a
(
lpszStoreProvider
),
dwMsgAndCertEncodingType
,
hCryptProv
,
dwFlags
,
pvPara
);
/* Stores an extended property in a cert. */
typedef
struct
_WINE_CERT_PROPERTY
{
WINE_CERT_PROP_HEADER
hdr
;
LPBYTE
pbData
;
struct
list
entry
;
}
WINE_CERT_PROPERTY
,
*
PWINE_CERT_PROPERTY
;
/* A mem store has a list of these. They're also returned by the mem store
* during enumeration.
*/
typedef
struct
_WINE_CERT_LIST_ENTRY
{
WINE_CERT_CONTEXT_REF
cert
;
struct
list
entry
;
}
WINE_CERT_LIST_ENTRY
,
*
PWINE_CERT_LIST_ENTRY
;
typedef
struct
_WINE_MEMSTORE
{
WINECRYPT_CERTSTORE
hdr
;
CRITICAL_SECTION
cs
;
struct
list
certs
;
}
WINE_MEMSTORE
,
*
PWINE_MEMSTORE
;
/* Like CertGetCertificateContextProperty, but operates directly on the
* WINE_CERT_CONTEXT. Doesn't support special-case properties, since they
* are handled by CertGetCertificateContextProperty, and are particular to the
* store in which the property exists (which is separate from the context.)
*/
static
BOOL
WINAPI
CRYPT_GetCertificateContextProperty
(
PWINE_CERT_CONTEXT
context
,
DWORD
dwPropId
,
void
*
pvData
,
DWORD
*
pcbData
);
/* Like CertSetCertificateContextProperty, but operates directly on the
* WINE_CERT_CONTEXT. Doesn't handle special cases, since they're handled by
* CertSetCertificateContextProperty anyway.
*/
static
BOOL
WINAPI
CRYPT_SetCertificateContextProperty
(
PWINE_CERT_CONTEXT
context
,
DWORD
dwPropId
,
DWORD
dwFlags
,
const
void
*
pvData
);
if
(
lpszStoreProvider
==
CERT_STORE_PROV_SYSTEM_A
)
static
void
CRYPT_InitStore
(
WINECRYPT_CERTSTORE
*
store
,
HCRYPTPROV
hCryptProv
,
DWORD
dwFlags
,
CertStoreType
type
)
{
store
->
ref
=
1
;
store
->
dwMagic
=
WINE_CRYPTCERTSTORE_MAGIC
;
store
->
type
=
type
;
if
(
!
hCryptProv
)
{
FIXME
(
"pvPara = %s
\n
"
,
debugstr_a
(
(
LPCSTR
)
pvPara
)
);
hCryptProv
=
CRYPT_GetDefaultProvider
();
dwFlags
|=
CERT_STORE_NO_CRYPT_RELEASE_FLAG
;
}
else
if
(
lpszStoreProvider
==
CERT_STORE_PROV_SYSTEM_W
)
store
->
cryptProv
=
hCryptProv
;
store
->
dwOpenFlags
=
dwFlags
;
}
/* Initializes the reference ref to point to pCertContext, which is assumed to
* be a PWINE_CERT_CONTEXT, and increments pCertContext's reference count.
* Also sets the hCertStore member of the reference to store.
*/
static
void
CRYPT_InitCertRef
(
PWINE_CERT_CONTEXT_REF
ref
,
PWINE_CERT_CONTEXT
context
,
HCERTSTORE
store
)
{
TRACE
(
"(%p, %p)
\n
"
,
ref
,
context
);
memcpy
(
&
ref
->
cert
,
context
,
sizeof
(
ref
->
cert
));
ref
->
context
=
context
;
InterlockedIncrement
(
&
context
->
ref
);
ref
->
cert
.
hCertStore
=
store
;
}
static
PWINE_CERT_CONTEXT_REF
CRYPT_CreateCertRef
(
PWINE_CERT_CONTEXT
context
,
HCERTSTORE
store
)
{
PWINE_CERT_CONTEXT_REF
pCertRef
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
WINE_CERT_CONTEXT_REF
));
if
(
pCertRef
)
CRYPT_InitCertRef
(
pCertRef
,
context
,
store
);
return
pCertRef
;
}
static
BOOL
WINAPI
CRYPT_MemAddCert
(
HCERTSTORE
store
,
PCCERT_CONTEXT
pCert
,
DWORD
dwAddDisposition
)
{
WINE_MEMSTORE
*
ms
=
(
WINE_MEMSTORE
*
)
store
;
BOOL
add
=
FALSE
,
ret
;
TRACE
(
"(%p, %p, %ld)
\n
"
,
store
,
pCert
,
dwAddDisposition
);
switch
(
dwAddDisposition
)
{
case
CERT_STORE_ADD_ALWAYS
:
add
=
TRUE
;
break
;
case
CERT_STORE_ADD_NEW
:
{
FIXME
(
"pvPara = %s
\n
"
,
debugstr_w
(
(
LPCWSTR
)
pvPara
)
);
BYTE
hashToAdd
[
20
],
hash
[
20
];
DWORD
size
=
sizeof
(
hashToAdd
);
ret
=
CRYPT_GetCertificateContextProperty
((
PWINE_CERT_CONTEXT
)
pCert
,
CERT_HASH_PROP_ID
,
hashToAdd
,
&
size
);
if
(
ret
)
{
PWINE_CERT_LIST_ENTRY
cursor
;
/* Add if no cert with the same hash is found. */
add
=
TRUE
;
EnterCriticalSection
(
&
ms
->
cs
);
LIST_FOR_EACH_ENTRY
(
cursor
,
&
ms
->
certs
,
WINE_CERT_LIST_ENTRY
,
entry
)
{
size
=
sizeof
(
hash
);
ret
=
CertGetCertificateContextProperty
(
&
cursor
->
cert
.
cert
,
CERT_HASH_PROP_ID
,
hash
,
&
size
);
if
(
ret
&&
!
memcmp
(
hashToAdd
,
hash
,
size
))
{
TRACE
(
"found matching certificate, not adding
\n
"
);
SetLastError
(
CRYPT_E_EXISTS
);
add
=
FALSE
;
break
;
}
}
LeaveCriticalSection
(
&
ms
->
cs
);
}
break
;
}
case
CERT_STORE_ADD_REPLACE_EXISTING
:
{
BYTE
hashToAdd
[
20
],
hash
[
20
];
DWORD
size
=
sizeof
(
hashToAdd
);
hcs
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
WINECRYPT_CERTSTORE
)
);
if
(
!
hcs
)
return
NULL
;
add
=
TRUE
;
ret
=
CRYPT_GetCertificateContextProperty
((
PWINE_CERT_CONTEXT
)
pCert
,
CERT_HASH_PROP_ID
,
hashToAdd
,
&
size
);
if
(
ret
)
{
PWINE_CERT_LIST_ENTRY
cursor
,
next
;
/* Look for existing cert to delete */
EnterCriticalSection
(
&
ms
->
cs
);
LIST_FOR_EACH_ENTRY_SAFE
(
cursor
,
next
,
&
ms
->
certs
,
WINE_CERT_LIST_ENTRY
,
entry
)
{
size
=
sizeof
(
hash
);
ret
=
CertGetCertificateContextProperty
(
&
cursor
->
cert
.
cert
,
CERT_HASH_PROP_ID
,
hash
,
&
size
);
if
(
ret
&&
!
memcmp
(
hashToAdd
,
hash
,
size
))
{
TRACE
(
"found matching certificate, replacing
\n
"
);
list_remove
(
&
cursor
->
entry
);
CertFreeCertificateContext
((
PCCERT_CONTEXT
)
cursor
);
break
;
}
}
LeaveCriticalSection
(
&
ms
->
cs
);
}
break
;
}
default:
FIXME
(
"Unimplemented add disposition %ld
\n
"
,
dwAddDisposition
);
add
=
FALSE
;
}
if
(
add
)
{
PWINE_CERT_LIST_ENTRY
entry
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
WINE_CERT_LIST_ENTRY
));
if
(
entry
)
{
TRACE
(
"adding %p
\n
"
,
entry
);
CRYPT_InitCertRef
(
&
entry
->
cert
,
(
PWINE_CERT_CONTEXT
)
pCert
,
store
);
list_init
(
&
entry
->
entry
);
EnterCriticalSection
(
&
ms
->
cs
);
list_add_tail
(
&
ms
->
certs
,
&
entry
->
entry
);
LeaveCriticalSection
(
&
ms
->
cs
);
ret
=
TRUE
;
}
else
ret
=
FALSE
;
}
else
ret
=
FALSE
;
return
ret
;
}
static
PWINE_CERT_CONTEXT_REF
CRYPT_MemEnumCert
(
PWINECRYPT_CERTSTORE
store
,
PWINE_CERT_CONTEXT_REF
pPrev
)
{
WINE_MEMSTORE
*
ms
=
(
WINE_MEMSTORE
*
)
store
;
PWINE_CERT_LIST_ENTRY
prevEntry
=
(
PWINE_CERT_LIST_ENTRY
)
pPrev
,
ret
;
struct
list
*
listNext
;
hcs
->
dwMagic
=
WINE_CRYPTCERTSTORE_MAGIC
;
TRACE
(
"(%p, %p)
\n
"
,
store
,
pPrev
);
EnterCriticalSection
(
&
ms
->
cs
);
if
(
prevEntry
)
{
listNext
=
list_next
(
&
ms
->
certs
,
&
prevEntry
->
entry
);
CertFreeCertificateContext
((
PCCERT_CONTEXT
)
pPrev
);
}
else
listNext
=
list_next
(
&
ms
->
certs
,
&
ms
->
certs
);
if
(
listNext
)
{
ret
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
WINE_CERT_LIST_ENTRY
));
memcpy
(
ret
,
LIST_ENTRY
(
listNext
,
WINE_CERT_LIST_ENTRY
,
entry
),
sizeof
(
WINE_CERT_LIST_ENTRY
));
InterlockedIncrement
(
&
ret
->
cert
.
context
->
ref
);
}
else
{
SetLastError
(
CRYPT_E_NOT_FOUND
);
ret
=
NULL
;
}
LeaveCriticalSection
(
&
ms
->
cs
);
return
(
HCERTSTORE
)
hcs
;
TRACE
(
"returning %p
\n
"
,
ret
);
return
(
PWINE_CERT_CONTEXT_REF
)
ret
;
}
static
BOOL
WINAPI
CRYPT_MemDeleteCert
(
HCERTSTORE
hCertStore
,
PCCERT_CONTEXT
pCertContext
,
DWORD
dwFlags
)
{
WINE_MEMSTORE
*
store
=
(
WINE_MEMSTORE
*
)
hCertStore
;
WINE_CERT_CONTEXT_REF
*
ref
=
(
WINE_CERT_CONTEXT_REF
*
)
pCertContext
;
PWINE_CERT_LIST_ENTRY
cert
,
next
;
BOOL
ret
;
/* Find the entry associated with the passed-in context, since the
* passed-in context may not be a list entry itself (e.g. if it came from
* CertDuplicateCertificateContext.) Pointing to the same context is
* a sufficient test of equality.
*/
EnterCriticalSection
(
&
store
->
cs
);
LIST_FOR_EACH_ENTRY_SAFE
(
cert
,
next
,
&
store
->
certs
,
WINE_CERT_LIST_ENTRY
,
entry
)
{
if
(
cert
->
cert
.
context
==
ref
->
context
)
{
TRACE
(
"removing %p
\n
"
,
cert
);
/* FIXME: this isn't entirely thread-safe, the entry itself isn't
* protected.
*/
list_remove
(
&
cert
->
entry
);
cert
->
entry
.
prev
=
cert
->
entry
.
next
=
&
store
->
certs
;
CertFreeCertificateContext
((
PCCERT_CONTEXT
)
cert
);
break
;
}
}
ret
=
TRUE
;
LeaveCriticalSection
(
&
store
->
cs
);
return
ret
;
}
static
void
WINAPI
CRYPT_MemCloseStore
(
HCERTSTORE
hCertStore
,
DWORD
dwFlags
)
{
WINE_MEMSTORE
*
store
=
(
WINE_MEMSTORE
*
)
hCertStore
;
PWINE_CERT_LIST_ENTRY
cert
,
next
;
TRACE
(
"(%p, %08lx)
\n
"
,
store
,
dwFlags
);
if
(
dwFlags
)
FIXME
(
"Unimplemented flags: %08lx
\n
"
,
dwFlags
);
/* Note that CertFreeCertificateContext calls HeapFree on the passed-in
* pointer if its ref-count reaches zero. That's okay here because there
* aren't any allocated data outside of the WINE_CERT_CONTEXT_REF portion
* of the CertListEntry.
*/
LIST_FOR_EACH_ENTRY_SAFE
(
cert
,
next
,
&
store
->
certs
,
WINE_CERT_LIST_ENTRY
,
entry
)
{
TRACE
(
"removing %p
\n
"
,
cert
);
list_remove
(
&
cert
->
entry
);
CertFreeCertificateContext
((
PCCERT_CONTEXT
)
cert
);
}
DeleteCriticalSection
(
&
store
->
cs
);
HeapFree
(
GetProcessHeap
(),
0
,
store
);
}
static
WINECRYPT_CERTSTORE
*
CRYPT_MemOpenStore
(
HCRYPTPROV
hCryptProv
,
DWORD
dwFlags
,
const
void
*
pvPara
)
{
PWINE_MEMSTORE
store
;
TRACE
(
"(%ld, %08lx, %p)
\n
"
,
hCryptProv
,
dwFlags
,
pvPara
);
if
(
dwFlags
&
CERT_STORE_DELETE_FLAG
)
{
SetLastError
(
ERROR_CALL_NOT_IMPLEMENTED
);
store
=
NULL
;
}
else
{
store
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
WINE_MEMSTORE
));
if
(
store
)
{
CRYPT_InitStore
(
&
store
->
hdr
,
hCryptProv
,
dwFlags
,
StoreTypeMem
);
store
->
hdr
.
closeStore
=
CRYPT_MemCloseStore
;
store
->
hdr
.
addCert
=
CRYPT_MemAddCert
;
store
->
hdr
.
createCertRef
=
CRYPT_CreateCertRef
;
store
->
hdr
.
enumCert
=
CRYPT_MemEnumCert
;
store
->
hdr
.
deleteCert
=
CRYPT_MemDeleteCert
;
store
->
hdr
.
freeCert
=
NULL
;
InitializeCriticalSection
(
&
store
->
cs
);
list_init
(
&
store
->
certs
);
}
}
return
(
PWINECRYPT_CERTSTORE
)
store
;
}
static
void
WINAPI
CRYPT_DummyCloseStore
(
HCERTSTORE
hCertStore
,
DWORD
dwFlags
)
{
HeapFree
(
GetProcessHeap
(),
0
,
(
PWINECRYPT_CERTSTORE
)
hCertStore
);
}
static
BOOL
WINAPI
CRYPT_DummyAddCert
(
HCERTSTORE
store
,
PCCERT_CONTEXT
pCert
,
DWORD
dwAddDisposition
)
{
return
FALSE
;
}
static
PWINE_CERT_CONTEXT_REF
CRYPT_DummyEnumCert
(
PWINECRYPT_CERTSTORE
store
,
PWINE_CERT_CONTEXT_REF
pPrev
)
{
return
NULL
;
}
static
BOOL
WINAPI
CRYPT_DummyDeleteCert
(
HCERTSTORE
hCertStore
,
PCCERT_CONTEXT
pCertContext
,
DWORD
dwFlags
)
{
return
TRUE
;
}
static
WINECRYPT_CERTSTORE
*
CRYPT_DummyOpenStore
(
HCRYPTPROV
hCryptProv
,
DWORD
dwFlags
,
const
void
*
pvPara
)
{
PWINECRYPT_CERTSTORE
store
;
TRACE
(
"(%ld, %08lx, %p)
\n
"
,
hCryptProv
,
dwFlags
,
pvPara
);
if
(
dwFlags
&
CERT_STORE_DELETE_FLAG
)
{
SetLastError
(
ERROR_CALL_NOT_IMPLEMENTED
);
store
=
NULL
;
}
else
{
store
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
WINECRYPT_CERTSTORE
));
if
(
store
)
{
CRYPT_InitStore
(
store
,
hCryptProv
,
dwFlags
,
StoreTypeDummy
);
store
->
closeStore
=
CRYPT_DummyCloseStore
;
store
->
addCert
=
CRYPT_DummyAddCert
;
store
->
createCertRef
=
CRYPT_CreateCertRef
;
store
->
enumCert
=
CRYPT_DummyEnumCert
;
store
->
deleteCert
=
CRYPT_DummyDeleteCert
;
store
->
freeCert
=
NULL
;
}
}
return
(
PWINECRYPT_CERTSTORE
)
store
;
}
HCERTSTORE
WINAPI
CertOpenStore
(
LPCSTR
lpszStoreProvider
,
DWORD
dwMsgAndCertEncodingType
,
HCRYPTPROV
hCryptProv
,
DWORD
dwFlags
,
const
void
*
pvPara
)
{
WINECRYPT_CERTSTORE
*
hcs
;
StoreOpenFunc
openFunc
=
NULL
;
TRACE
(
"(%s, %08lx, %08lx, %08lx, %p)
\n
"
,
debugstr_a
(
lpszStoreProvider
),
dwMsgAndCertEncodingType
,
hCryptProv
,
dwFlags
,
pvPara
);
if
(
!
HIWORD
(
lpszStoreProvider
))
{
switch
(
LOWORD
(
lpszStoreProvider
))
{
case
(
int
)
CERT_STORE_PROV_MEMORY
:
openFunc
=
CRYPT_MemOpenStore
;
break
;
case
(
int
)
CERT_STORE_PROV_REG
:
case
(
int
)
CERT_STORE_PROV_SYSTEM_A
:
case
(
int
)
CERT_STORE_PROV_SYSTEM_W
:
case
(
int
)
CERT_STORE_PROV_COLLECTION
:
openFunc
=
CRYPT_DummyOpenStore
;
break
;
default:
if
(
LOWORD
(
lpszStoreProvider
))
FIXME
(
"unimplemented type %d
\n
"
,
LOWORD
(
lpszStoreProvider
));
}
}
else
if
(
!
strcasecmp
(
lpszStoreProvider
,
sz_CERT_STORE_PROV_MEMORY
))
openFunc
=
CRYPT_MemOpenStore
;
else
if
(
!
strcasecmp
(
lpszStoreProvider
,
sz_CERT_STORE_PROV_SYSTEM
))
openFunc
=
CRYPT_DummyOpenStore
;
else
if
(
!
strcasecmp
(
lpszStoreProvider
,
sz_CERT_STORE_PROV_COLLECTION
))
openFunc
=
CRYPT_DummyOpenStore
;
else
{
FIXME
(
"unimplemented type %s
\n
"
,
lpszStoreProvider
);
openFunc
=
NULL
;
}
if
(
!
openFunc
)
{
/* FIXME: need to look for an installed provider for this type */
SetLastError
(
ERROR_FILE_NOT_FOUND
);
hcs
=
NULL
;
}
else
hcs
=
openFunc
(
hCryptProv
,
dwFlags
,
pvPara
);
return
(
HCERTSTORE
)
hcs
;
}
HCERTSTORE
WINAPI
CertOpenSystemStoreA
(
HCRYPTPROV
hProv
,
...
...
@@ -89,12 +565,6 @@ HCERTSTORE WINAPI CertOpenSystemStoreW(HCRYPTPROV hProv,
CERT_SYSTEM_STORE_USERS
,
szSubSystemProtocol
);
}
PCCERT_CONTEXT
WINAPI
CertEnumCertificatesInStore
(
HCERTSTORE
hCertStore
,
PCCERT_CONTEXT
pPrev
)
{
FIXME
(
"(%p,%p)
\n
"
,
hCertStore
,
pPrev
);
return
NULL
;
}
BOOL
WINAPI
CertSaveStore
(
HCERTSTORE
hCertStore
,
DWORD
dwMsgAndCertEncodingType
,
DWORD
dwSaveAs
,
DWORD
dwSaveTo
,
void
*
pvSaveToPara
,
DWORD
dwFlags
)
{
...
...
@@ -103,21 +573,6 @@ BOOL WINAPI CertSaveStore(HCERTSTORE hCertStore, DWORD dwMsgAndCertEncodingType,
return
TRUE
;
}
PCCERT_CONTEXT
WINAPI
CertCreateCertificateContext
(
DWORD
dwCertEncodingType
,
const
BYTE
*
pbCertEncoded
,
DWORD
cbCertEncoded
)
{
FIXME
(
"(%08lx, %p, %ld): stub
\n
"
,
dwCertEncodingType
,
pbCertEncoded
,
cbCertEncoded
);
return
NULL
;
}
PCCERT_CONTEXT
WINAPI
CertDuplicateCertificateContext
(
PCCERT_CONTEXT
pCertContext
)
{
FIXME
(
"(%p): stub
\n
"
,
pCertContext
);
return
NULL
;
}
PCCRL_CONTEXT
WINAPI
CertCreateCRLContext
(
DWORD
dwCertEncodingType
,
const
BYTE
*
pbCrlEncoded
,
DWORD
cbCrlEncoded
)
{
...
...
@@ -147,29 +602,558 @@ PCCRL_CONTEXT WINAPI CertCreateCRLContext( DWORD dwCertEncodingType,
return
pcrl
;
}
BOOL
WINAPI
CertAddEncodedCertificateToStore
(
HCERTSTORE
hCertStore
,
DWORD
dwCertEncodingType
,
const
BYTE
*
pbCertEncoded
,
DWORD
cbCertEncoded
,
DWORD
dwAddDisposition
,
PCCERT_CONTEXT
*
ppCertContext
)
/* Decodes the encoded certificate and creates the certificate context for it.
* The reference count is initially zero, so you must create a reference to it
* to avoid leaking memory.
*/
static
PWINE_CERT_CONTEXT
CRYPT_CreateCertificateContext
(
DWORD
dwCertEncodingType
,
const
BYTE
*
pbCertEncoded
,
DWORD
cbCertEncoded
)
{
FIXME
(
"(%p, %08lx, %p, %ld, %08lx, %p): stub
\n
"
,
hCertStore
,
dwCertEncodingType
,
pbCertEncoded
,
cbCertEncoded
,
dwAddDisposition
,
ppCertContext
);
return
FALSE
;
PWINE_CERT_CONTEXT
cert
=
NULL
;
BOOL
ret
;
PCERT_INFO
certInfo
=
NULL
;
DWORD
size
=
0
;
TRACE
(
"(%08lx, %p, %ld)
\n
"
,
dwCertEncodingType
,
pbCertEncoded
,
cbCertEncoded
);
ret
=
CryptDecodeObjectEx
(
X509_ASN_ENCODING
,
X509_CERT_TO_BE_SIGNED
,
pbCertEncoded
,
cbCertEncoded
,
CRYPT_DECODE_ALLOC_FLAG
|
CRYPT_DECODE_NOCOPY_FLAG
,
NULL
,
(
BYTE
*
)
&
certInfo
,
&
size
);
if
(
ret
)
{
BYTE
*
data
=
NULL
;
cert
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
WINE_CERT_CONTEXT
));
if
(
!
cert
)
goto
end
;
data
=
HeapAlloc
(
GetProcessHeap
(),
0
,
cbCertEncoded
);
if
(
!
data
)
{
HeapFree
(
GetProcessHeap
(),
0
,
cert
);
cert
=
NULL
;
goto
end
;
}
memcpy
(
data
,
pbCertEncoded
,
cbCertEncoded
);
cert
->
cert
.
dwCertEncodingType
=
dwCertEncodingType
;
cert
->
cert
.
pbCertEncoded
=
data
;
cert
->
cert
.
cbCertEncoded
=
cbCertEncoded
;
cert
->
cert
.
pCertInfo
=
certInfo
;
cert
->
cert
.
hCertStore
=
0
;
cert
->
ref
=
0
;
InitializeCriticalSection
(
&
cert
->
cs
);
list_init
(
&
cert
->
extendedProperties
);
}
end:
return
cert
;
}
static
void
CRYPT_FreeCert
(
PWINE_CERT_CONTEXT
context
)
{
PWINE_CERT_PROPERTY
prop
,
next
;
HeapFree
(
GetProcessHeap
(),
0
,
context
->
cert
.
pbCertEncoded
);
LocalFree
(
context
->
cert
.
pCertInfo
);
HeapFree
(
GetProcessHeap
(),
0
,
context
);
DeleteCriticalSection
(
&
context
->
cs
);
LIST_FOR_EACH_ENTRY_SAFE
(
prop
,
next
,
&
context
->
extendedProperties
,
WINE_CERT_PROPERTY
,
entry
)
{
list_remove
(
&
prop
->
entry
);
HeapFree
(
GetProcessHeap
(),
0
,
prop
->
pbData
);
HeapFree
(
GetProcessHeap
(),
0
,
prop
);
}
}
PCCERT_CONTEXT
WINAPI
CertCreateCertificateContext
(
DWORD
dwCertEncodingType
,
const
BYTE
*
pbCertEncoded
,
DWORD
cbCertEncoded
)
{
PWINE_CERT_CONTEXT
cert
;
PWINE_CERT_CONTEXT_REF
ret
=
NULL
;
TRACE
(
"(%08lx, %p, %ld)
\n
"
,
dwCertEncodingType
,
pbCertEncoded
,
cbCertEncoded
);
cert
=
CRYPT_CreateCertificateContext
(
dwCertEncodingType
,
pbCertEncoded
,
cbCertEncoded
);
if
(
cert
)
ret
=
CRYPT_CreateCertRef
(
cert
,
0
);
return
(
PCCERT_CONTEXT
)
ret
;
}
/* Since the properties are stored in a list, this is a tad inefficient
* (O(n^2)) since I have to find the previous position every time.
*/
DWORD
WINAPI
CertEnumCertificateContextProperties
(
PCCERT_CONTEXT
pCertContext
,
DWORD
dwPropId
)
{
PWINE_CERT_CONTEXT_REF
ref
=
(
PWINE_CERT_CONTEXT_REF
)
pCertContext
;
DWORD
ret
;
TRACE
(
"(%p, %ld)
\n
"
,
pCertContext
,
dwPropId
);
EnterCriticalSection
(
&
ref
->
context
->
cs
);
if
(
dwPropId
)
{
PWINE_CERT_PROPERTY
cursor
=
NULL
;
LIST_FOR_EACH_ENTRY
(
cursor
,
&
ref
->
context
->
extendedProperties
,
WINE_CERT_PROPERTY
,
entry
)
{
if
(
cursor
->
hdr
.
propID
==
dwPropId
)
break
;
}
if
(
cursor
)
{
if
(
cursor
->
entry
.
next
!=
&
ref
->
context
->
extendedProperties
)
ret
=
LIST_ENTRY
(
cursor
->
entry
.
next
,
WINE_CERT_PROPERTY
,
entry
)
->
hdr
.
propID
;
else
ret
=
0
;
}
else
ret
=
0
;
}
else
if
(
!
list_empty
(
&
ref
->
context
->
extendedProperties
))
ret
=
LIST_ENTRY
(
ref
->
context
->
extendedProperties
.
next
,
WINE_CERT_PROPERTY
,
entry
)
->
hdr
.
propID
;
else
ret
=
0
;
LeaveCriticalSection
(
&
ref
->
context
->
cs
);
return
ret
;
}
static
BOOL
WINAPI
CRYPT_GetCertificateContextProperty
(
PWINE_CERT_CONTEXT
context
,
DWORD
dwPropId
,
void
*
pvData
,
DWORD
*
pcbData
)
{
PWINE_CERT_PROPERTY
prop
;
BOOL
ret
,
found
;
TRACE
(
"(%p, %ld, %p, %p)
\n
"
,
context
,
dwPropId
,
pvData
,
pcbData
);
EnterCriticalSection
(
&
context
->
cs
);
ret
=
FALSE
;
found
=
FALSE
;
LIST_FOR_EACH_ENTRY
(
prop
,
&
context
->
extendedProperties
,
WINE_CERT_PROPERTY
,
entry
)
{
if
(
prop
->
hdr
.
propID
==
dwPropId
)
{
if
(
!
pvData
)
{
*
pcbData
=
prop
->
hdr
.
cb
;
ret
=
TRUE
;
}
else
if
(
*
pcbData
<
prop
->
hdr
.
cb
)
{
SetLastError
(
ERROR_MORE_DATA
);
*
pcbData
=
prop
->
hdr
.
cb
;
}
else
{
memcpy
(
pvData
,
prop
->
pbData
,
prop
->
hdr
.
cb
);
*
pcbData
=
prop
->
hdr
.
cb
;
ret
=
TRUE
;
}
found
=
TRUE
;
}
break
;
}
if
(
!
found
)
{
/* Implicit properties */
switch
(
dwPropId
)
{
case
CERT_SHA1_HASH_PROP_ID
:
ret
=
CryptHashCertificate
(
0
,
CALG_SHA1
,
0
,
context
->
cert
.
pbCertEncoded
,
context
->
cert
.
cbCertEncoded
,
pvData
,
pcbData
);
if
(
ret
)
{
CRYPT_DATA_BLOB
blob
=
{
*
pcbData
,
pvData
};
ret
=
CRYPT_SetCertificateContextProperty
(
context
,
dwPropId
,
0
,
&
blob
);
}
break
;
case
CERT_KEY_PROV_INFO_PROP_ID
:
case
CERT_MD5_HASH_PROP_ID
:
case
CERT_SIGNATURE_HASH_PROP_ID
:
case
CERT_KEY_IDENTIFIER_PROP_ID
:
case
CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID
:
case
CERT_ISSUER_SERIAL_NUMBER_MD5_HASH_PROP_ID
:
case
CERT_SUBJECT_NAME_MD5_HASH_PROP_ID
:
FIXME
(
"implicit property %ld
\n
"
,
dwPropId
);
break
;
}
}
LeaveCriticalSection
(
&
context
->
cs
);
TRACE
(
"returning %d
\n
"
,
ret
);
return
ret
;
}
BOOL
WINAPI
CertGetCertificateContextProperty
(
PCCERT_CONTEXT
pCertContext
,
DWORD
dwPropId
,
void
*
pvData
,
DWORD
*
pcbData
)
{
PWINE_CERT_CONTEXT_REF
ref
=
(
PWINE_CERT_CONTEXT_REF
)
pCertContext
;
BOOL
ret
;
TRACE
(
"(%p, %ld, %p, %p)
\n
"
,
pCertContext
,
dwPropId
,
pvData
,
pcbData
);
/* Special cases for invalid/special prop IDs.
*/
switch
(
dwPropId
)
{
case
0
:
case
CERT_CERT_PROP_ID
:
case
CERT_CRL_PROP_ID
:
case
CERT_CTL_PROP_ID
:
SetLastError
(
HRESULT_FROM_WIN32
(
ERROR_INVALID_PARAMETER
));
return
FALSE
;
case
CERT_ACCESS_STATE_PROP_ID
:
if
(
!
pvData
)
{
*
pcbData
=
sizeof
(
DWORD
);
return
TRUE
;
}
else
if
(
*
pcbData
<
sizeof
(
DWORD
))
{
SetLastError
(
ERROR_MORE_DATA
);
*
pcbData
=
sizeof
(
DWORD
);
return
FALSE
;
}
else
{
DWORD
state
=
0
;
if
(
pCertContext
->
hCertStore
)
{
PWINECRYPT_CERTSTORE
store
=
(
PWINECRYPT_CERTSTORE
)
pCertContext
->
hCertStore
;
/* Take advantage of knowledge of the stores to answer the
* access state question
*/
if
(
store
->
type
!=
StoreTypeReg
||
!
(
store
->
dwOpenFlags
&
CERT_STORE_READONLY_FLAG
))
state
|=
CERT_ACCESS_STATE_WRITE_PERSIST_FLAG
;
}
*
(
DWORD
*
)
pvData
=
state
;
return
TRUE
;
}
}
ret
=
CRYPT_GetCertificateContextProperty
(
ref
->
context
,
dwPropId
,
pvData
,
pcbData
);
TRACE
(
"returning %d
\n
"
,
ret
);
return
ret
;
}
/* Copies cbData bytes from pbData to the context's property with ID
* dwPropId.
*/
static
BOOL
CRYPT_SaveCertificateContextProperty
(
PWINE_CERT_CONTEXT
context
,
DWORD
dwPropId
,
const
BYTE
*
pbData
,
size_t
cbData
)
{
BOOL
ret
=
FALSE
;
LPBYTE
data
;
if
(
cbData
)
{
data
=
HeapAlloc
(
GetProcessHeap
(),
0
,
cbData
);
if
(
data
)
memcpy
(
data
,
pbData
,
cbData
);
}
else
data
=
NULL
;
if
(
!
cbData
||
data
)
{
PWINE_CERT_PROPERTY
prop
;
EnterCriticalSection
(
&
context
->
cs
);
LIST_FOR_EACH_ENTRY
(
prop
,
&
context
->
extendedProperties
,
WINE_CERT_PROPERTY
,
entry
)
{
if
(
prop
->
hdr
.
propID
==
dwPropId
)
break
;
}
if
(
prop
&&
prop
->
entry
.
next
!=
&
context
->
extendedProperties
)
{
HeapFree
(
GetProcessHeap
(),
0
,
prop
->
pbData
);
prop
->
hdr
.
cb
=
cbData
;
prop
->
pbData
=
cbData
?
data
:
NULL
;
ret
=
TRUE
;
}
else
{
prop
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
WINE_CERT_PROPERTY
));
if
(
prop
)
{
prop
->
hdr
.
propID
=
dwPropId
;
prop
->
hdr
.
unknown
=
1
;
prop
->
hdr
.
cb
=
cbData
;
list_init
(
&
prop
->
entry
);
prop
->
pbData
=
cbData
?
data
:
NULL
;
list_add_tail
(
&
context
->
extendedProperties
,
&
prop
->
entry
);
ret
=
TRUE
;
}
else
HeapFree
(
GetProcessHeap
(),
0
,
data
);
}
LeaveCriticalSection
(
&
context
->
cs
);
}
return
ret
;
}
static
BOOL
WINAPI
CRYPT_SetCertificateContextProperty
(
PWINE_CERT_CONTEXT
context
,
DWORD
dwPropId
,
DWORD
dwFlags
,
const
void
*
pvData
)
{
BOOL
ret
=
FALSE
;
TRACE
(
"(%p, %ld, %08lx, %p)
\n
"
,
context
,
dwPropId
,
dwFlags
,
pvData
);
if
(
!
pvData
)
{
PWINE_CERT_PROPERTY
prop
,
next
;
EnterCriticalSection
(
&
context
->
cs
);
LIST_FOR_EACH_ENTRY_SAFE
(
prop
,
next
,
&
context
->
extendedProperties
,
WINE_CERT_PROPERTY
,
entry
)
{
if
(
prop
->
hdr
.
propID
==
dwPropId
)
{
list_remove
(
&
prop
->
entry
);
HeapFree
(
GetProcessHeap
(),
0
,
prop
->
pbData
);
HeapFree
(
GetProcessHeap
(),
0
,
prop
);
}
}
LeaveCriticalSection
(
&
context
->
cs
);
ret
=
TRUE
;
}
else
{
switch
(
dwPropId
)
{
case
CERT_AUTO_ENROLL_PROP_ID
:
case
CERT_CTL_USAGE_PROP_ID
:
case
CERT_DESCRIPTION_PROP_ID
:
case
CERT_FRIENDLY_NAME_PROP_ID
:
case
CERT_HASH_PROP_ID
:
case
CERT_KEY_IDENTIFIER_PROP_ID
:
case
CERT_MD5_HASH_PROP_ID
:
case
CERT_NEXT_UPDATE_LOCATION_PROP_ID
:
case
CERT_PUBKEY_ALG_PARA_PROP_ID
:
case
CERT_PVK_FILE_PROP_ID
:
case
CERT_SIGNATURE_HASH_PROP_ID
:
case
CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID
:
case
CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID
:
case
CERT_ENROLLMENT_PROP_ID
:
case
CERT_CROSS_CERT_DIST_POINTS_PROP_ID
:
case
CERT_RENEWAL_PROP_ID
:
{
PCRYPT_DATA_BLOB
blob
=
(
PCRYPT_DATA_BLOB
)
pvData
;
ret
=
CRYPT_SaveCertificateContextProperty
(
context
,
dwPropId
,
blob
->
pbData
,
blob
->
cbData
);
break
;
}
case
CERT_DATE_STAMP_PROP_ID
:
ret
=
CRYPT_SaveCertificateContextProperty
(
context
,
dwPropId
,
pvData
,
sizeof
(
FILETIME
));
break
;
default:
FIXME
(
"%ld: stub
\n
"
,
dwPropId
);
}
}
TRACE
(
"returning %d
\n
"
,
ret
);
return
ret
;
}
BOOL
WINAPI
CertSetCertificateContextProperty
(
PCCERT_CONTEXT
pCertContext
,
DWORD
dwPropId
,
DWORD
dwFlags
,
const
void
*
pvData
)
{
PWINE_CERT_CONTEXT_REF
ref
=
(
PWINE_CERT_CONTEXT_REF
)
pCertContext
;
BOOL
ret
;
TRACE
(
"(%p, %ld, %08lx, %p)
\n
"
,
pCertContext
,
dwPropId
,
dwFlags
,
pvData
);
/* Handle special cases for "read-only"/invalid prop IDs. Windows just
* crashes on most of these, I'll be safer.
*/
switch
(
dwPropId
)
{
case
0
:
case
CERT_ACCESS_STATE_PROP_ID
:
case
CERT_CERT_PROP_ID
:
case
CERT_CRL_PROP_ID
:
case
CERT_CTL_PROP_ID
:
SetLastError
(
HRESULT_FROM_WIN32
(
ERROR_INVALID_PARAMETER
));
return
FALSE
;
}
ret
=
CRYPT_SetCertificateContextProperty
(
ref
->
context
,
dwPropId
,
dwFlags
,
pvData
);
TRACE
(
"returning %d
\n
"
,
ret
);
return
ret
;
}
/* Only the reference portion of the context is duplicated. The returned
* context has the cert store set to 0, to prevent the store's certificate free
* function from getting called on partial data.
* FIXME: is this okay? Needs a test.
*/
PCCERT_CONTEXT
WINAPI
CertDuplicateCertificateContext
(
PCCERT_CONTEXT
pCertContext
)
{
PWINE_CERT_CONTEXT_REF
ref
=
(
PWINE_CERT_CONTEXT_REF
)
pCertContext
,
ret
;
TRACE
(
"(%p)
\n
"
,
pCertContext
);
if
(
ref
)
{
ret
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
WINE_CERT_CONTEXT_REF
));
if
(
ret
)
{
memcpy
(
ret
,
ref
,
sizeof
(
*
ret
));
ret
->
cert
.
hCertStore
=
0
;
InterlockedIncrement
(
&
ret
->
context
->
ref
);
}
}
else
ret
=
NULL
;
return
(
PCCERT_CONTEXT
)
ret
;
}
BOOL
WINAPI
CertAddCertificateContextToStore
(
HCERTSTORE
hCertStore
,
PCCERT_CONTEXT
pCertContext
,
DWORD
dwAddDisposition
,
PCCERT_CONTEXT
*
ppStoreContext
)
{
FIXME
(
"(%p, %p, %08lx, %p): stub
\n
"
,
hCertStore
,
pCertContext
,
PWINECRYPT_CERTSTORE
store
=
(
PWINECRYPT_CERTSTORE
)
hCertStore
;
PWINE_CERT_CONTEXT_REF
ref
=
(
PWINE_CERT_CONTEXT_REF
)
pCertContext
;
PWINE_CERT_CONTEXT
cert
;
BOOL
ret
;
TRACE
(
"(%p, %p, %08lx, %p)
\n
"
,
hCertStore
,
pCertContext
,
dwAddDisposition
,
ppStoreContext
);
return
FALSE
;
/* FIXME: some tests needed to verify return codes */
if
(
!
store
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
if
(
store
->
dwMagic
!=
WINE_CRYPTCERTSTORE_MAGIC
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
cert
=
CRYPT_CreateCertificateContext
(
ref
->
context
->
cert
.
dwCertEncodingType
,
ref
->
context
->
cert
.
pbCertEncoded
,
ref
->
context
->
cert
.
cbCertEncoded
);
if
(
cert
)
{
PWINE_CERT_PROPERTY
prop
;
ret
=
TRUE
;
EnterCriticalSection
(
&
ref
->
context
->
cs
);
LIST_FOR_EACH_ENTRY
(
prop
,
&
ref
->
context
->
extendedProperties
,
WINE_CERT_PROPERTY
,
entry
)
{
ret
=
CRYPT_SaveCertificateContextProperty
(
cert
,
prop
->
hdr
.
propID
,
prop
->
pbData
,
prop
->
hdr
.
cb
);
if
(
!
ret
)
break
;
}
LeaveCriticalSection
(
&
ref
->
context
->
cs
);
if
(
ret
)
{
ret
=
store
->
addCert
(
store
,
(
PCCERT_CONTEXT
)
cert
,
dwAddDisposition
);
if
(
ret
&&
ppStoreContext
)
*
ppStoreContext
=
(
PCCERT_CONTEXT
)
store
->
createCertRef
(
cert
,
hCertStore
);
}
if
(
!
ret
)
CRYPT_FreeCert
(
cert
);
}
else
ret
=
FALSE
;
return
ret
;
}
BOOL
WINAPI
CertAddEncodedCertificateToStore
(
HCERTSTORE
hCertStore
,
DWORD
dwCertEncodingType
,
const
BYTE
*
pbCertEncoded
,
DWORD
cbCertEncoded
,
DWORD
dwAddDisposition
,
PCCERT_CONTEXT
*
ppCertContext
)
{
WINECRYPT_CERTSTORE
*
hcs
=
(
WINECRYPT_CERTSTORE
*
)
hCertStore
;
BOOL
ret
;
TRACE
(
"(%p, %08lx, %p, %ld, %08lx, %p)
\n
"
,
hCertStore
,
dwCertEncodingType
,
pbCertEncoded
,
cbCertEncoded
,
dwAddDisposition
,
ppCertContext
);
if
(
!
hcs
)
ret
=
FALSE
;
else
if
(
hcs
->
dwMagic
!=
WINE_CRYPTCERTSTORE_MAGIC
)
ret
=
FALSE
;
else
{
PWINE_CERT_CONTEXT
cert
=
CRYPT_CreateCertificateContext
(
dwCertEncodingType
,
pbCertEncoded
,
cbCertEncoded
);
if
(
cert
)
{
ret
=
hcs
->
addCert
(
hcs
,
(
PCCERT_CONTEXT
)
cert
,
dwAddDisposition
);
if
(
ret
&&
ppCertContext
)
*
ppCertContext
=
(
PCCERT_CONTEXT
)
hcs
->
createCertRef
(
cert
,
hCertStore
);
if
(
!
ret
)
CRYPT_FreeCert
(
cert
);
}
else
ret
=
FALSE
;
}
return
ret
;
}
PCCERT_CONTEXT
WINAPI
CertEnumCertificatesInStore
(
HCERTSTORE
hCertStore
,
PCCERT_CONTEXT
pPrev
)
{
WINECRYPT_CERTSTORE
*
hcs
=
(
WINECRYPT_CERTSTORE
*
)
hCertStore
;
PWINE_CERT_CONTEXT_REF
prev
=
(
PWINE_CERT_CONTEXT_REF
)
pPrev
;
PCCERT_CONTEXT
ret
;
TRACE
(
"(%p, %p)
\n
"
,
hCertStore
,
pPrev
);
if
(
!
hCertStore
)
ret
=
NULL
;
else
if
(
hcs
->
dwMagic
!=
WINE_CRYPTCERTSTORE_MAGIC
)
ret
=
NULL
;
else
ret
=
(
PCCERT_CONTEXT
)
hcs
->
enumCert
(
hcs
,
prev
);
return
ret
;
}
BOOL
WINAPI
CertDeleteCertificateFromStore
(
PCCERT_CONTEXT
pCertContext
)
{
FIXME
(
"(%p): stub
\n
"
,
pCertContext
);
return
FALSE
;
BOOL
ret
;
TRACE
(
"(%p)
\n
"
,
pCertContext
);
if
(
!
pCertContext
)
ret
=
TRUE
;
else
if
(
!
pCertContext
->
hCertStore
)
ret
=
TRUE
;
else
{
PWINECRYPT_CERTSTORE
hcs
=
(
PWINECRYPT_CERTSTORE
)
pCertContext
->
hCertStore
;
if
(
!
hcs
)
ret
=
TRUE
;
else
if
(
hcs
->
dwMagic
!=
WINE_CRYPTCERTSTORE_MAGIC
)
ret
=
FALSE
;
else
ret
=
hcs
->
deleteCert
(
hcs
,
pCertContext
,
0
);
}
return
ret
;
}
BOOL
WINAPI
CertAddEncodedCRLToStore
(
HCERTSTORE
hCertStore
,
...
...
@@ -258,20 +1242,28 @@ PCCTL_CONTEXT WINAPI CertEnumCTLsInStore(HCERTSTORE hCertStore,
}
BOOL
WINAPI
CertCloseStore
(
HCERTSTORE
hCertStore
,
DWORD
dwFlags
)
BOOL
WINAPI
CertCloseStore
(
HCERTSTORE
hCertStore
,
DWORD
dwFlags
)
{
WINECRYPT_CERTSTORE
*
hcs
=
(
WINECRYPT_CERTSTORE
*
)
hCertStore
;
FIXME
(
"%p %08lx
\n
"
,
hCertStore
,
dwFlags
);
TRACE
(
"(%p, %08lx)
\n
"
,
hCertStore
,
dwFlags
);
if
(
!
hCertStore
)
return
FALS
E
;
return
TRU
E
;
if
(
hcs
->
dwMagic
!=
WINE_CRYPTCERTSTORE_MAGIC
)
return
FALSE
;
hcs
->
dwMagic
=
0
;
HeapFree
(
GetProcessHeap
(),
0
,
hCertStore
);
if
(
InterlockedDecrement
(
&
hcs
->
ref
)
==
0
)
{
TRACE
(
"freeing %p
\n
"
,
hcs
);
hcs
->
dwMagic
=
0
;
if
(
!
(
hcs
->
dwOpenFlags
&
CERT_STORE_NO_CRYPT_RELEASE_FLAG
))
CryptReleaseContext
(
hcs
->
cryptProv
,
0
);
hcs
->
closeStore
(
hcs
,
dwFlags
);
}
else
TRACE
(
"%p's ref count is %ld
\n
"
,
hcs
,
hcs
->
ref
);
return
TRUE
;
}
...
...
@@ -283,28 +1275,6 @@ BOOL WINAPI CertControlStore(HCERTSTORE hCertStore, DWORD dwFlags,
return
TRUE
;
}
DWORD
WINAPI
CertEnumCertificateContextProperties
(
PCCERT_CONTEXT
pCertContext
,
DWORD
dwPropId
)
{
FIXME
(
"(%p, %ld): stub
\n
"
,
pCertContext
,
dwPropId
);
return
0
;
}
BOOL
WINAPI
CertGetCertificateContextProperty
(
PCCERT_CONTEXT
pCertContext
,
DWORD
dwPropId
,
void
*
pvData
,
DWORD
*
pcbData
)
{
FIXME
(
"(%p, %ld, %p, %p): stub
\n
"
,
pCertContext
,
dwPropId
,
pvData
,
pcbData
);
return
FALSE
;
}
BOOL
WINAPI
CertSetCertificateContextProperty
(
PCCERT_CONTEXT
pCertContext
,
DWORD
dwPropId
,
DWORD
dwFlags
,
const
void
*
pvData
)
{
FIXME
(
"(%p, %ld, %08lx, %p): stub
\n
"
,
pCertContext
,
dwPropId
,
dwFlags
,
pvData
);
return
FALSE
;
}
BOOL
WINAPI
CertGetCRLContextProperty
(
PCCRL_CONTEXT
pCRLContext
,
DWORD
dwPropId
,
void
*
pvData
,
DWORD
*
pcbData
)
{
...
...
@@ -354,9 +1324,61 @@ BOOL WINAPI CertSerializeCTLStoreElement(PCCTL_CONTEXT pCtlContext,
BOOL
WINAPI
CertSerializeCertificateStoreElement
(
PCCERT_CONTEXT
pCertContext
,
DWORD
dwFlags
,
BYTE
*
pbElement
,
DWORD
*
pcbElement
)
{
FIXME
(
"(%p, %08lx, %p, %p): stub
\n
"
,
pCertContext
,
dwFlags
,
pbElement
,
BOOL
ret
;
TRACE
(
"(%p, %08lx, %p, %p)
\n
"
,
pCertContext
,
dwFlags
,
pbElement
,
pcbElement
);
return
FALSE
;
if
(
pCertContext
)
{
PWINE_CERT_CONTEXT_REF
ref
=
(
PWINE_CERT_CONTEXT_REF
)
pCertContext
;
DWORD
bytesNeeded
=
sizeof
(
WINE_CERT_PROP_HEADER
)
+
pCertContext
->
cbCertEncoded
;
PWINE_CERT_PROPERTY
prop
;
EnterCriticalSection
(
&
ref
->
context
->
cs
);
LIST_FOR_EACH_ENTRY
(
prop
,
&
ref
->
context
->
extendedProperties
,
WINE_CERT_PROPERTY
,
entry
)
bytesNeeded
+=
sizeof
(
WINE_CERT_PROP_HEADER
)
+
prop
->
hdr
.
cb
;
if
(
!
pbElement
)
{
*
pcbElement
=
bytesNeeded
;
ret
=
TRUE
;
}
else
if
(
*
pcbElement
<
bytesNeeded
)
{
*
pcbElement
=
bytesNeeded
;
SetLastError
(
ERROR_MORE_DATA
);
ret
=
FALSE
;
}
else
{
PWINE_CERT_PROP_HEADER
hdr
;
LIST_FOR_EACH_ENTRY
(
prop
,
&
ref
->
context
->
extendedProperties
,
WINE_CERT_PROPERTY
,
entry
)
{
memcpy
(
pbElement
,
&
prop
->
hdr
,
sizeof
(
WINE_CERT_PROP_HEADER
));
pbElement
+=
sizeof
(
WINE_CERT_PROP_HEADER
);
if
(
prop
->
hdr
.
cb
)
{
memcpy
(
pbElement
,
prop
->
pbData
,
prop
->
hdr
.
cb
);
pbElement
+=
prop
->
hdr
.
cb
;
}
}
hdr
=
(
PWINE_CERT_PROP_HEADER
)
pbElement
;
hdr
->
propID
=
CERT_CERT_PROP_ID
;
hdr
->
unknown
=
1
;
hdr
->
cb
=
pCertContext
->
cbCertEncoded
;
memcpy
(
pbElement
+
sizeof
(
WINE_CERT_PROP_HEADER
),
pCertContext
->
pbCertEncoded
,
pCertContext
->
cbCertEncoded
);
ret
=
TRUE
;
}
LeaveCriticalSection
(
&
ref
->
context
->
cs
);
}
else
ret
=
FALSE
;
return
ret
;
}
BOOL
WINAPI
CertAddSerializedElementToStore
(
HCERTSTORE
hCertStore
,
...
...
@@ -369,9 +1391,28 @@ BOOL WINAPI CertAddSerializedElementToStore(HCERTSTORE hCertStore,
return
FALSE
;
}
BOOL
WINAPI
CertFreeCertificateContext
(
PCCERT_CONTEXT
pCertContext
)
BOOL
WINAPI
CertFreeCertificateContext
(
PCCERT_CONTEXT
pCertContext
)
{
FIXME
(
"%p stub
\n
"
,
pCertContext
);
TRACE
(
"(%p)
\n
"
,
pCertContext
);
if
(
pCertContext
)
{
PWINE_CERT_CONTEXT_REF
ref
=
(
PWINE_CERT_CONTEXT_REF
)
pCertContext
;
PWINECRYPT_CERTSTORE
store
=
(
PWINECRYPT_CERTSTORE
)
ref
->
cert
.
hCertStore
;
if
(
InterlockedDecrement
(
&
ref
->
context
->
ref
)
==
0
)
{
TRACE
(
"freeing %p
\n
"
,
ref
->
context
);
CRYPT_FreeCert
(
ref
->
context
);
}
else
TRACE
(
"%p's ref count is %ld
\n
"
,
ref
->
context
,
ref
->
context
->
ref
);
if
(
store
&&
store
->
dwMagic
==
WINE_CRYPTCERTSTORE_MAGIC
&&
store
->
freeCert
)
store
->
freeCert
(
ref
);
HeapFree
(
GetProcessHeap
(),
0
,
ref
);
}
return
TRUE
;
}
...
...
dlls/crypt32/tests/cert.c
View file @
8d1cf4eb
...
...
@@ -64,7 +64,309 @@ static void testCryptHashCert(void)
ok
(
!
memcmp
(
hash
,
knownHash
,
sizeof
(
knownHash
)),
"Unexpected hash
\n
"
);
}
static
const
BYTE
emptyCert
[]
=
{
0x30
,
0x00
};
static
const
BYTE
bigCert
[]
=
"
\x30\x7a\x02\x01\x01\x30\x02\x06\x00
"
"
\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x4a\x75\x61\x6e\x20\x4c
"
"
\x61\x6e\x67\x00\x30\x22\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30
"
"
\x30\x30\x30\x5a\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30
"
"
\x30\x5a\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x4a\x75\x61\x6e
"
"
\x20\x4c\x61\x6e\x67\x00\x30\x07\x30\x02\x06\x00\x03\x01\x00\xa3\x16\x30\x14
"
"
\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01
"
"
\x01
"
;
static
const
BYTE
signedBigCert
[]
=
{
0x30
,
0x81
,
0x93
,
0x30
,
0x7a
,
0x02
,
0x01
,
0x01
,
0x30
,
0x02
,
0x06
,
0x00
,
0x30
,
0x15
,
0x31
,
0x13
,
0x30
,
0x11
,
0x06
,
0x03
,
0x55
,
0x04
,
0x03
,
0x13
,
0x0a
,
0x4a
,
0x75
,
0x61
,
0x6e
,
0x20
,
0x4c
,
0x61
,
0x6e
,
0x67
,
0x00
,
0x30
,
0x22
,
0x18
,
0x0f
,
0x31
,
0x36
,
0x30
,
0x31
,
0x30
,
0x31
,
0x30
,
0x31
,
0x30
,
0x30
,
0x30
,
0x30
,
0x30
,
0x30
,
0x5a
,
0x18
,
0x0f
,
0x31
,
0x36
,
0x30
,
0x31
,
0x30
,
0x31
,
0x30
,
0x31
,
0x30
,
0x30
,
0x30
,
0x30
,
0x30
,
0x30
,
0x5a
,
0x30
,
0x15
,
0x31
,
0x13
,
0x30
,
0x11
,
0x06
,
0x03
,
0x55
,
0x04
,
0x03
,
0x13
,
0x0a
,
0x4a
,
0x75
,
0x61
,
0x6e
,
0x20
,
0x4c
,
0x61
,
0x6e
,
0x67
,
0x00
,
0x30
,
0x07
,
0x30
,
0x02
,
0x06
,
0x00
,
0x03
,
0x01
,
0x00
,
0xa3
,
0x16
,
0x30
,
0x14
,
0x30
,
0x12
,
0x06
,
0x03
,
0x55
,
0x1d
,
0x13
,
0x01
,
0x01
,
0xff
,
0x04
,
0x08
,
0x30
,
0x06
,
0x01
,
0x01
,
0xff
,
0x02
,
0x01
,
0x01
,
0x30
,
0x02
,
0x06
,
0x00
,
0x03
,
0x11
,
0x00
,
0x0f
,
0x0e
,
0x0d
,
0x0c
,
0x0b
,
0x0a
,
0x09
,
0x08
,
0x07
,
0x06
,
0x05
,
0x04
,
0x03
,
0x02
,
0x01
,
0x00
};
static
const
BYTE
serializedCert
[]
=
{
0x20
,
0x00
,
0x00
,
0x00
,
0x01
,
0x00
,
0x00
,
0x00
,
0x7c
,
0x00
,
0x00
,
0x00
,
0x30
,
0x7a
,
0x02
,
0x01
,
0x01
,
0x30
,
0x02
,
0x06
,
0x00
,
0x30
,
0x15
,
0x31
,
0x13
,
0x30
,
0x11
,
0x06
,
0x03
,
0x55
,
0x04
,
0x03
,
0x13
,
0x0a
,
0x4a
,
0x75
,
0x61
,
0x6e
,
0x20
,
0x4c
,
0x61
,
0x6e
,
0x67
,
0x00
,
0x30
,
0x22
,
0x18
,
0x0f
,
0x31
,
0x36
,
0x30
,
0x31
,
0x30
,
0x31
,
0x30
,
0x31
,
0x30
,
0x30
,
0x30
,
0x30
,
0x30
,
0x30
,
0x5a
,
0x18
,
0x0f
,
0x31
,
0x36
,
0x30
,
0x31
,
0x30
,
0x31
,
0x30
,
0x31
,
0x30
,
0x30
,
0x30
,
0x30
,
0x30
,
0x30
,
0x5a
,
0x30
,
0x15
,
0x31
,
0x13
,
0x30
,
0x11
,
0x06
,
0x03
,
0x55
,
0x04
,
0x03
,
0x13
,
0x0a
,
0x4a
,
0x75
,
0x61
,
0x6e
,
0x20
,
0x4c
,
0x61
,
0x6e
,
0x67
,
0x00
,
0x30
,
0x07
,
0x30
,
0x02
,
0x06
,
0x00
,
0x03
,
0x01
,
0x00
,
0xa3
,
0x16
,
0x30
,
0x14
,
0x30
,
0x12
,
0x06
,
0x03
,
0x55
,
0x1d
,
0x13
,
0x01
,
0x01
,
0xff
,
0x04
,
0x08
,
0x30
,
0x06
,
0x01
,
0x01
,
0xff
,
0x02
,
0x01
,
0x01
};
static
void
testMemStore
(
void
)
{
HCERTSTORE
store1
,
store2
;
PCCERT_CONTEXT
context
;
BOOL
ret
;
/* NULL provider */
store1
=
CertOpenStore
(
0
,
0
,
0
,
0
,
NULL
);
ok
(
!
store1
&&
GetLastError
()
==
ERROR_FILE_NOT_FOUND
,
"Expected ERROR_FILE_NOT_FOUND, got %ld
\n
"
,
GetLastError
());
/* weird flags */
store1
=
CertOpenStore
(
CERT_STORE_PROV_MEMORY
,
0
,
0
,
CERT_STORE_DELETE_FLAG
,
NULL
);
ok
(
!
store1
&&
GetLastError
()
==
ERROR_CALL_NOT_IMPLEMENTED
,
"Expected ERROR_CALL_NOT_IMPLEMENTED, got %ld
\n
"
,
GetLastError
());
/* normal */
store1
=
CertOpenStore
(
CERT_STORE_PROV_MEMORY
,
0
,
0
,
CERT_STORE_CREATE_NEW_FLAG
,
NULL
);
ok
(
store1
!=
NULL
,
"CertOpenStore failed: %ld
\n
"
,
GetLastError
());
/* open existing doesn't */
store2
=
CertOpenStore
(
CERT_STORE_PROV_MEMORY
,
0
,
0
,
CERT_STORE_OPEN_EXISTING_FLAG
,
NULL
);
ok
(
store2
!=
NULL
,
"CertOpenStore failed: %ld
\n
"
,
GetLastError
());
ok
(
store1
!=
store2
,
"Expected different stores
\n
"
);
/* add a bogus (empty) cert */
context
=
NULL
;
ret
=
CertAddEncodedCertificateToStore
(
store1
,
X509_ASN_ENCODING
,
emptyCert
,
sizeof
(
emptyCert
),
CERT_STORE_ADD_ALWAYS
,
&
context
);
/* Windows returns CRYPT_E_ASN1_EOD, but accept CRYPT_E_ASN1_CORRUPT as
* well (because matching errors is tough in this case)
*/
ok
(
!
ret
&&
(
GetLastError
()
==
CRYPT_E_ASN1_EOD
||
GetLastError
()
==
CRYPT_E_ASN1_CORRUPT
),
"Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08lx
\n
"
,
GetLastError
());
/* add a signed cert (this also fails) */
ok
(
!
ret
&&
(
GetLastError
()
==
CRYPT_E_ASN1_EOD
||
GetLastError
()
==
CRYPT_E_ASN1_CORRUPT
),
"Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08lx
\n
"
,
GetLastError
());
ret
=
CertAddEncodedCertificateToStore
(
store1
,
X509_ASN_ENCODING
,
signedBigCert
,
sizeof
(
signedBigCert
)
-
1
,
CERT_STORE_ADD_ALWAYS
,
&
context
);
/* add a cert to store1 */
ret
=
CertAddEncodedCertificateToStore
(
store1
,
X509_ASN_ENCODING
,
bigCert
,
sizeof
(
bigCert
)
-
1
,
CERT_STORE_ADD_ALWAYS
,
&
context
);
ok
(
ret
,
"CertAddEncodedCertificateToStore failed: %08lx
\n
"
,
GetLastError
());
ok
(
context
!=
NULL
,
"Expected a valid cert context
\n
"
);
if
(
context
)
{
DWORD
size
;
BYTE
*
buf
;
ok
(
context
->
cbCertEncoded
==
sizeof
(
bigCert
)
-
1
,
"Expected cert of %d bytes, got %ld
\n
"
,
sizeof
(
bigCert
)
-
1
,
context
->
cbCertEncoded
);
ok
(
!
memcmp
(
context
->
pbCertEncoded
,
bigCert
,
sizeof
(
bigCert
)
-
1
),
"Unexpected encoded cert in context
\n
"
);
ok
(
context
->
hCertStore
==
store1
,
"Unexpected store
\n
"
);
/* check serializing this element */
/* These crash
ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, NULL);
ret = CertSerializeCertificateStoreElement(context, 0, NULL, NULL);
ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, &size);
*/
/* apparently flags are ignored */
ret
=
CertSerializeCertificateStoreElement
(
context
,
1
,
NULL
,
&
size
);
ok
(
ret
,
"CertSerializeCertificateStoreElement failed: %08lx
\n
"
,
GetLastError
());
buf
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
);
if
(
buf
)
{
ret
=
CertSerializeCertificateStoreElement
(
context
,
0
,
buf
,
&
size
);
ok
(
size
==
sizeof
(
serializedCert
),
"Expected size %d, got %ld
\n
"
,
sizeof
(
serializedCert
),
size
);
ok
(
!
memcmp
(
serializedCert
,
buf
,
size
),
"Unexpected serialized cert
\n
"
);
HeapFree
(
GetProcessHeap
(),
0
,
buf
);
}
ret
=
CertFreeCertificateContext
(
context
);
ok
(
ret
,
"CertFreeCertificateContext failed: %08lx
\n
"
,
GetLastError
());
}
/* verify the cert's in store1 */
context
=
CertEnumCertificatesInStore
(
store1
,
NULL
);
ok
(
context
!=
NULL
,
"Expected a valid context
\n
"
);
context
=
CertEnumCertificatesInStore
(
store1
,
context
);
ok
(
!
context
&&
GetLastError
()
==
CRYPT_E_NOT_FOUND
,
"Expected CRYPT_E_NOT_FOUND, got %08lx
\n
"
,
GetLastError
());
/* verify store2 (the "open existing" mem store) is still empty */
context
=
CertEnumCertificatesInStore
(
store2
,
NULL
);
ok
(
!
context
,
"Expected an empty store
\n
"
);
/* delete the cert from store1, and check it's empty */
context
=
CertEnumCertificatesInStore
(
store1
,
NULL
);
if
(
context
)
{
/* Deleting a bitwise copy crashes with an access to an uninitialized
* pointer, so a cert context has some special data out there in memory
* someplace
CERT_CONTEXT copy;
memcpy(©, context, sizeof(copy));
ret = CertDeleteCertificateFromStore(©);
*/
PCCERT_CONTEXT
copy
=
CertDuplicateCertificateContext
(
context
);
ok
(
copy
!=
NULL
,
"CertDuplicateCertificateContext failed: %08lx
\n
"
,
GetLastError
());
ret
=
CertDeleteCertificateFromStore
(
context
);
ok
(
ret
,
"CertDeleteCertificateFromStore failed: %08lx
\n
"
,
GetLastError
());
/* try deleting a copy */
ret
=
CertDeleteCertificateFromStore
(
copy
);
ok
(
ret
,
"CertDeleteCertificateFromStore failed: %08lx
\n
"
,
GetLastError
());
/* check that the store is empty */
context
=
CertEnumCertificatesInStore
(
store1
,
NULL
);
ok
(
!
context
,
"Expected an empty store
\n
"
);
}
/* close an empty store */
ret
=
CertCloseStore
(
NULL
,
0
);
ok
(
ret
,
"CertCloseStore failed: %ld
\n
"
,
GetLastError
());
ret
=
CertCloseStore
(
store1
,
0
);
ok
(
ret
,
"CertCloseStore failed: %ld
\n
"
,
GetLastError
());
ret
=
CertCloseStore
(
store2
,
0
);
ok
(
ret
,
"CertCloseStore failed: %ld
\n
"
,
GetLastError
());
/* This seems nonsensical, but you can open a read-only mem store, only
* it isn't read-only
*/
store1
=
CertOpenStore
(
CERT_STORE_PROV_MEMORY
,
0
,
0
,
CERT_STORE_READONLY_FLAG
,
NULL
);
ok
(
store1
!=
NULL
,
"CertOpenStore failed: %ld
\n
"
,
GetLastError
());
/* yep, this succeeds */
ret
=
CertAddEncodedCertificateToStore
(
store1
,
X509_ASN_ENCODING
,
bigCert
,
sizeof
(
bigCert
)
-
1
,
CERT_STORE_ADD_ALWAYS
,
&
context
);
ok
(
ret
,
"CertAddEncodedCertificateToStore failed: %08lx
\n
"
,
GetLastError
());
ok
(
context
!=
NULL
,
"Expected a valid cert context
\n
"
);
if
(
context
)
{
ok
(
context
->
cbCertEncoded
==
sizeof
(
bigCert
)
-
1
,
"Expected cert of %d bytes, got %ld
\n
"
,
sizeof
(
bigCert
)
-
1
,
context
->
cbCertEncoded
);
ok
(
!
memcmp
(
context
->
pbCertEncoded
,
bigCert
,
sizeof
(
bigCert
)
-
1
),
"Unexpected encoded cert in context
\n
"
);
ok
(
context
->
hCertStore
==
store1
,
"Unexpected store
\n
"
);
ret
=
CertDeleteCertificateFromStore
(
context
);
ok
(
ret
,
"CertDeleteCertificateFromStore failed: %08lx
\n
"
,
GetLastError
());
}
CertCloseStore
(
store1
,
0
);
}
static
void
testCertProperties
(
void
)
{
PCCERT_CONTEXT
context
=
CertCreateCertificateContext
(
X509_ASN_ENCODING
,
bigCert
,
sizeof
(
bigCert
)
-
1
);
ok
(
context
!=
NULL
,
"CertCreateCertificateContext failed: %08lx
\n
"
,
GetLastError
());
if
(
context
)
{
DWORD
propID
,
numProps
,
access
,
size
;
BOOL
ret
;
BYTE
hash
[
20
]
=
{
0
},
hashProperty
[
20
];
CRYPT_DATA_BLOB
blob
;
/* This crashes
propID = CertEnumCertificateContextProperties(NULL, 0);
*/
propID
=
0
;
numProps
=
0
;
do
{
propID
=
CertEnumCertificateContextProperties
(
context
,
propID
);
if
(
propID
)
numProps
++
;
}
while
(
propID
!=
0
);
ok
(
numProps
==
0
,
"Expected 0 properties, got %ld
\n
"
,
numProps
);
/* Tests with a NULL cert context. Prop ID 0 fails.. */
ret
=
CertSetCertificateContextProperty
(
NULL
,
0
,
0
,
NULL
);
ok
(
!
ret
&&
GetLastError
()
==
HRESULT_FROM_WIN32
(
ERROR_INVALID_PARAMETER
),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx
\n
"
,
GetLastError
());
/* while this just crashes.
ret = CertSetCertificateContextProperty(NULL,
CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
*/
ret
=
CertSetCertificateContextProperty
(
context
,
0
,
0
,
NULL
);
ok
(
!
ret
&&
GetLastError
()
==
HRESULT_FROM_WIN32
(
ERROR_INVALID_PARAMETER
),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx
\n
"
,
GetLastError
());
/* Can't set the cert property directly, this crashes.
ret = CertSetCertificateContextProperty(context,
CERT_CERT_PROP_ID, 0, bigCert2);
*/
/* This crashes.
ret = CertGetCertificateContextProperty(context,
CERT_ACCESS_STATE_PROP_ID, 0, NULL);
*/
size
=
sizeof
(
access
);
ret
=
CertGetCertificateContextProperty
(
context
,
CERT_ACCESS_STATE_PROP_ID
,
&
access
,
&
size
);
ok
(
ret
,
"CertGetCertificateContextProperty failed: %08lx
\n
"
,
GetLastError
());
ok
(
!
(
access
&
CERT_ACCESS_STATE_WRITE_PERSIST_FLAG
),
"Didn't expect a persisted cert
\n
"
);
/* Trying to set this "read only" property crashes.
access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
ret = CertSetCertificateContextProperty(context,
CERT_ACCESS_STATE_PROP_ID, 0, &access);
*/
/* Can I set the hash to an invalid hash? */
blob
.
pbData
=
hash
;
blob
.
cbData
=
sizeof
(
hash
);
ret
=
CertSetCertificateContextProperty
(
context
,
CERT_HASH_PROP_ID
,
0
,
&
blob
);
ok
(
ret
,
"CertSetCertificateContextProperty failed: %08lx
\n
"
,
GetLastError
());
size
=
sizeof
(
hashProperty
);
ret
=
CertGetCertificateContextProperty
(
context
,
CERT_HASH_PROP_ID
,
hashProperty
,
&
size
);
ok
(
!
memcmp
(
hashProperty
,
hash
,
sizeof
(
hash
)),
"Unexpected hash
\n
"
);
/* Delete the (bogus) hash, and get the real one */
ret
=
CertSetCertificateContextProperty
(
context
,
CERT_HASH_PROP_ID
,
0
,
NULL
);
ok
(
ret
,
"CertSetCertificateContextProperty failed: %08lx
\n
"
,
GetLastError
());
size
=
sizeof
(
hash
);
ret
=
CryptHashCertificate
(
0
,
0
,
0
,
bigCert
,
sizeof
(
bigCert
)
-
1
,
hash
,
&
size
);
ok
(
ret
,
"CryptHashCertificate failed: %08lx
\n
"
,
GetLastError
());
ret
=
CertGetCertificateContextProperty
(
context
,
CERT_HASH_PROP_ID
,
hashProperty
,
&
size
);
ok
(
ret
,
"CertGetCertificateContextProperty failed: %08lx
\n
"
,
GetLastError
());
ok
(
!
memcmp
(
hash
,
hashProperty
,
sizeof
(
hash
)),
"Unexpected hash
\n
"
);
/* Now that the hash property is set, we should get one property when
* enumerating.
*/
propID
=
0
;
numProps
=
0
;
do
{
propID
=
CertEnumCertificateContextProperties
(
context
,
propID
);
if
(
propID
)
numProps
++
;
}
while
(
propID
!=
0
);
ok
(
numProps
==
1
,
"Expected 1 properties, got %ld
\n
"
,
numProps
);
CertFreeCertificateContext
(
context
);
}
}
START_TEST
(
cert
)
{
testCryptHashCert
();
/* various combinations of CertOpenStore */
testMemStore
();
testCertProperties
();
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment