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
22 #define WIN32_NO_STATUS
27 #include "crypt32_private.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
33 static HCRYPTPROV
import_key( cert_store_data_t data
, DWORD flags
)
37 DWORD size
, acquire_flags
;
39 struct import_store_key_params params
= { data
, NULL
, &size
};
41 if (CRYPT32_CALL( import_store_key
, ¶ms
) != STATUS_BUFFER_TOO_SMALL
) return 0;
43 acquire_flags
= (flags
& CRYPT_MACHINE_KEYSET
) | CRYPT_NEWKEYSET
;
44 if (!CryptAcquireContextW( &prov
, NULL
, MS_ENHANCED_PROV_W
, PROV_RSA_FULL
, acquire_flags
))
46 if (GetLastError() != NTE_EXISTS
) return 0;
48 acquire_flags
&= ~CRYPT_NEWKEYSET
;
49 if (!CryptAcquireContextW( &prov
, NULL
, MS_ENHANCED_PROV_W
, PROV_RSA_FULL
, acquire_flags
))
51 WARN( "CryptAcquireContextW failed %08lx\n", GetLastError() );
56 params
.buf
= key
= CryptMemAlloc( size
);
57 if (CRYPT32_CALL( import_store_key
, ¶ms
) ||
58 !CryptImportKey( prov
, key
, size
, 0, flags
& CRYPT_EXPORTABLE
, &cryptkey
))
60 WARN( "CryptImportKey failed %08lx\n", GetLastError() );
61 CryptReleaseContext( prov
, 0 );
65 CryptDestroyKey( cryptkey
);
70 static BOOL
set_key_context( const void *ctx
, HCRYPTPROV prov
)
72 CERT_KEY_CONTEXT key_ctx
;
73 key_ctx
.cbSize
= sizeof(key_ctx
);
74 key_ctx
.hCryptProv
= prov
;
75 key_ctx
.dwKeySpec
= AT_KEYEXCHANGE
;
76 return CertSetCertificateContextProperty( ctx
, CERT_KEY_CONTEXT_PROP_ID
, 0, &key_ctx
);
79 static WCHAR
*get_provider_property( HCRYPTPROV prov
, DWORD prop_id
, DWORD
*len
)
85 CryptGetProvParam( prov
, prop_id
, NULL
, &size
, 0 );
86 if (!size
) return NULL
;
87 if (!(str
= CryptMemAlloc( size
))) return NULL
;
88 CryptGetProvParam( prov
, prop_id
, (BYTE
*)str
, &size
, 0 );
90 *len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
91 if ((ret
= CryptMemAlloc( *len
* sizeof(WCHAR
) ))) MultiByteToWideChar( CP_ACP
, 0, str
, -1, ret
, *len
);
96 static BOOL
set_key_prov_info( const void *ctx
, HCRYPTPROV prov
)
98 CRYPT_KEY_PROV_INFO
*prov_info
;
99 DWORD size
, len_container
, len_name
;
100 WCHAR
*ptr
, *container
, *name
;
103 if (!(container
= get_provider_property( prov
, PP_CONTAINER
, &len_container
))) return FALSE
;
104 if (!(name
= get_provider_property( prov
, PP_NAME
, &len_name
)))
106 CryptMemFree( container
);
109 if (!(prov_info
= CryptMemAlloc( sizeof(*prov_info
) + (len_container
+ len_name
) * sizeof(WCHAR
) )))
111 CryptMemFree( container
);
112 CryptMemFree( name
);
116 ptr
= (WCHAR
*)(prov_info
+ 1);
117 prov_info
->pwszContainerName
= ptr
;
118 lstrcpyW( prov_info
->pwszContainerName
, container
);
120 ptr
+= len_container
;
121 prov_info
->pwszProvName
= ptr
;
122 lstrcpyW( prov_info
->pwszProvName
, name
);
124 size
= sizeof(prov_info
->dwProvType
);
125 CryptGetProvParam( prov
, PP_PROVTYPE
, (BYTE
*)&prov_info
->dwProvType
, &size
, 0 );
127 prov_info
->dwFlags
= 0;
128 prov_info
->cProvParam
= 0;
129 prov_info
->rgProvParam
= NULL
;
130 size
= sizeof(prov_info
->dwKeySpec
);
131 CryptGetProvParam( prov
, PP_KEYSPEC
, (BYTE
*)&prov_info
->dwKeySpec
, &size
, 0 );
133 ret
= CertSetCertificateContextProperty( ctx
, CERT_KEY_PROV_INFO_PROP_ID
, 0, prov_info
);
135 CryptMemFree( prov_info
);
136 CryptMemFree( name
);
137 CryptMemFree( container
);
141 HCERTSTORE WINAPI
PFXImportCertStore( CRYPT_DATA_BLOB
*pfx
, const WCHAR
*password
, DWORD flags
)
144 HCERTSTORE store
= NULL
;
146 cert_store_data_t data
= 0;
147 struct open_cert_store_params open_params
= { pfx
, password
, &data
};
148 struct close_cert_store_params close_params
;
152 SetLastError( ERROR_INVALID_PARAMETER
);
155 if (flags
& ~(CRYPT_EXPORTABLE
|CRYPT_USER_KEYSET
|CRYPT_MACHINE_KEYSET
|PKCS12_NO_PERSIST_KEY
))
157 FIXME( "flags %08lx not supported\n", flags
);
160 if (CRYPT32_CALL( open_cert_store
, &open_params
)) return NULL
;
162 prov
= import_key( data
, flags
);
163 if (!prov
) goto error
;
165 if (!(store
= CertOpenStore( CERT_STORE_PROV_MEMORY
, 0, 0, 0, NULL
)))
167 WARN( "CertOpenStore failed %08lx\n", GetLastError() );
173 const void *ctx
= NULL
;
175 struct import_store_cert_params import_params
= { data
, i
, NULL
, &size
};
177 if (CRYPT32_CALL( import_store_cert
, &import_params
) != STATUS_BUFFER_TOO_SMALL
) break;
178 import_params
.buf
= cert
= CryptMemAlloc( size
);
179 if (!CRYPT32_CALL( import_store_cert
, &import_params
))
180 ctx
= CertCreateContext( CERT_STORE_CERTIFICATE_CONTEXT
, X509_ASN_ENCODING
, cert
, size
, 0, NULL
);
181 CryptMemFree( cert
);
184 WARN( "CertCreateContext failed %08lx\n", GetLastError() );
187 if (flags
& PKCS12_NO_PERSIST_KEY
)
189 if (!set_key_context( ctx
, prov
))
191 WARN( "failed to set context property %08lx\n", GetLastError() );
192 CertFreeCertificateContext( ctx
);
196 else if (!set_key_prov_info( ctx
, prov
))
198 WARN( "failed to set provider info property %08lx\n", GetLastError() );
199 CertFreeCertificateContext( ctx
);
202 if (!CertAddCertificateContextToStore( store
, ctx
, CERT_STORE_ADD_ALWAYS
, NULL
))
204 WARN( "CertAddCertificateContextToStore failed %08lx\n", GetLastError() );
205 CertFreeCertificateContext( ctx
);
208 CertFreeCertificateContext( ctx
);
211 close_params
.data
= data
;
212 CRYPT32_CALL( close_cert_store
, &close_params
);
216 CryptReleaseContext( prov
, 0 );
217 CertCloseStore( store
, 0 );
218 close_params
.data
= data
;
219 CRYPT32_CALL( close_cert_store
, &close_params
);
223 BOOL WINAPI
PFXVerifyPassword( CRYPT_DATA_BLOB
*pfx
, const WCHAR
*password
, DWORD flags
)
225 FIXME( "(%p, %p, %08lx): stub\n", pfx
, password
, flags
);
229 BOOL WINAPI
PFXExportCertStore( HCERTSTORE store
, CRYPT_DATA_BLOB
*pfx
, const WCHAR
*password
, DWORD flags
)
231 return PFXExportCertStoreEx( store
, pfx
, password
, NULL
, flags
);
234 BOOL WINAPI
PFXExportCertStoreEx( HCERTSTORE store
, CRYPT_DATA_BLOB
*pfx
, const WCHAR
*password
, void *reserved
,
237 FIXME( "(%p, %p, %p, %p, %08lx): stub\n", store
, pfx
, password
, reserved
, flags
);