2 * Copyright 2019 Hans Leidekker for CodeWeavers
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
25 #include "crypt32_private.h"
27 #include "wine/debug.h"
28 #include "wine/heap.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
32 static HCRYPTPROV
import_key( void *key
, DWORD flags
)
36 DWORD size
, acquire_flags
;
38 size
= HeapSize( GetProcessHeap(), 0, key
);
39 acquire_flags
= (flags
& CRYPT_MACHINE_KEYSET
) | CRYPT_NEWKEYSET
;
40 if (!CryptAcquireContextW( &prov
, NULL
, MS_ENHANCED_PROV_W
, PROV_RSA_FULL
, acquire_flags
))
42 if (GetLastError() != NTE_EXISTS
) return 0;
44 acquire_flags
&= ~CRYPT_NEWKEYSET
;
45 if (!CryptAcquireContextW( &prov
, NULL
, MS_ENHANCED_PROV_W
, PROV_RSA_FULL
, acquire_flags
))
47 WARN( "CryptAcquireContextW failed %08x\n", GetLastError() );
52 if (!CryptImportKey( prov
, key
, size
, 0, flags
& CRYPT_EXPORTABLE
, &cryptkey
))
54 WARN( "CryptImportKey failed %08x\n", GetLastError() );
55 CryptReleaseContext( prov
, 0 );
58 CryptDestroyKey( cryptkey
);
62 static BOOL
set_key_context( const void *ctx
, HCRYPTPROV prov
)
64 CERT_KEY_CONTEXT key_ctx
;
65 key_ctx
.cbSize
= sizeof(key_ctx
);
66 key_ctx
.hCryptProv
= prov
;
67 key_ctx
.dwKeySpec
= AT_KEYEXCHANGE
;
68 return CertSetCertificateContextProperty( ctx
, CERT_KEY_CONTEXT_PROP_ID
, 0, &key_ctx
);
71 static WCHAR
*get_provider_property( HCRYPTPROV prov
, DWORD prop_id
, DWORD
*len
)
77 CryptGetProvParam( prov
, prop_id
, NULL
, &size
, 0 );
78 if (!size
) return NULL
;
79 if (!(str
= CryptMemAlloc( size
))) return NULL
;
80 CryptGetProvParam( prov
, prop_id
, (BYTE
*)str
, &size
, 0 );
82 *len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
83 if ((ret
= CryptMemAlloc( *len
* sizeof(WCHAR
) ))) MultiByteToWideChar( CP_ACP
, 0, str
, -1, ret
, *len
);
88 static BOOL
set_key_prov_info( const void *ctx
, HCRYPTPROV prov
)
90 CRYPT_KEY_PROV_INFO
*prov_info
;
91 DWORD size
, len_container
, len_name
;
92 WCHAR
*ptr
, *container
, *name
;
95 if (!(container
= get_provider_property( prov
, PP_CONTAINER
, &len_container
))) return FALSE
;
96 if (!(name
= get_provider_property( prov
, PP_NAME
, &len_name
)))
98 CryptMemFree( container
);
101 if (!(prov_info
= CryptMemAlloc( sizeof(*prov_info
) + (len_container
+ len_name
) * sizeof(WCHAR
) )))
103 CryptMemFree( container
);
104 CryptMemFree( name
);
108 ptr
= (WCHAR
*)(prov_info
+ 1);
109 prov_info
->pwszContainerName
= ptr
;
110 lstrcpyW( prov_info
->pwszContainerName
, container
);
112 ptr
+= len_container
;
113 prov_info
->pwszProvName
= ptr
;
114 lstrcpyW( prov_info
->pwszProvName
, name
);
116 size
= sizeof(prov_info
->dwProvType
);
117 CryptGetProvParam( prov
, PP_PROVTYPE
, (BYTE
*)&prov_info
->dwProvType
, &size
, 0 );
119 prov_info
->dwFlags
= 0;
120 prov_info
->cProvParam
= 0;
121 prov_info
->rgProvParam
= NULL
;
122 size
= sizeof(prov_info
->dwKeySpec
);
123 CryptGetProvParam( prov
, PP_KEYSPEC
, (BYTE
*)&prov_info
->dwKeySpec
, &size
, 0 );
125 ret
= CertSetCertificateContextProperty( ctx
, CERT_KEY_PROV_INFO_PROP_ID
, 0, prov_info
);
127 CryptMemFree( prov_info
);
128 CryptMemFree( name
);
129 CryptMemFree( container
);
133 HCERTSTORE WINAPI
PFXImportCertStore( CRYPT_DATA_BLOB
*pfx
, const WCHAR
*password
, DWORD flags
)
136 DWORD i
, chain_len
= 0;
137 HCERTSTORE store
= NULL
;
142 SetLastError( ERROR_INVALID_PARAMETER
);
145 if (flags
& ~(CRYPT_EXPORTABLE
|CRYPT_USER_KEYSET
|CRYPT_MACHINE_KEYSET
|PKCS12_NO_PERSIST_KEY
))
147 FIXME( "flags %08x not supported\n", flags
);
150 if (!unix_funcs
->import_cert_store
)
152 FIXME( "(%p, %p, %08x)\n", pfx
, password
, flags
);
155 if (!unix_funcs
->import_cert_store( pfx
, password
, flags
, &key
, &chain
, &chain_len
)) return NULL
;
157 prov
= import_key( key
, flags
);
159 if (!prov
) goto error
;
161 if (!(store
= CertOpenStore( CERT_STORE_PROV_MEMORY
, 0, 0, 0, NULL
)))
163 WARN( "CertOpenStore failed %08x\n", GetLastError() );
167 if (chain_len
> 1) FIXME( "handle certificate chain\n" );
168 for (i
= 0; i
< chain_len
; i
++)
171 size_t size
= HeapSize( GetProcessHeap(), 0, chain
[i
] );
173 if (!(ctx
= CertCreateContext( CERT_STORE_CERTIFICATE_CONTEXT
, X509_ASN_ENCODING
,
174 chain
[i
], size
, 0, NULL
)))
176 WARN( "CertCreateContext failed %08x\n", GetLastError() );
179 if (flags
& PKCS12_NO_PERSIST_KEY
)
181 if (!set_key_context( ctx
, prov
))
183 WARN( "failed to set context property %08x\n", GetLastError() );
184 CertFreeCertificateContext( ctx
);
188 else if (!set_key_prov_info( ctx
, prov
))
190 WARN( "failed to set provider info property %08x\n", GetLastError() );
191 CertFreeCertificateContext( ctx
);
194 if (!CertAddCertificateContextToStore( store
, ctx
, CERT_STORE_ADD_ALWAYS
, NULL
))
196 WARN( "CertAddCertificateContextToStore failed %08x\n", GetLastError() );
197 CertFreeCertificateContext( ctx
);
200 CertFreeCertificateContext( ctx
);
202 while (chain_len
) heap_free( chain
[--chain_len
] );
207 CryptReleaseContext( prov
, 0 );
208 CertCloseStore( store
, 0 );
209 while (chain_len
) heap_free( chain
[--chain_len
] );
214 BOOL WINAPI
PFXVerifyPassword( CRYPT_DATA_BLOB
*pfx
, const WCHAR
*password
, DWORD flags
)
216 FIXME( "(%p, %p, %08x): stub\n", pfx
, password
, flags
);
220 BOOL WINAPI
PFXExportCertStore( HCERTSTORE store
, CRYPT_DATA_BLOB
*pfx
, const WCHAR
*password
, DWORD flags
)
222 return PFXExportCertStoreEx( store
, pfx
, password
, NULL
, flags
);
225 BOOL WINAPI
PFXExportCertStoreEx( HCERTSTORE store
, CRYPT_DATA_BLOB
*pfx
, const WCHAR
*password
, void *reserved
,
228 FIXME( "(%p, %p, %p, %p, %08x): stub\n", store
, pfx
, password
, reserved
, flags
);