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
23 #define WIN32_NO_STATUS
28 #include "crypt32_private.h"
30 #include "wine/debug.h"
31 #include "wine/heap.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
35 static HCRYPTPROV
import_key( struct cert_store_data
*data
, DWORD flags
)
39 DWORD size
, acquire_flags
;
41 struct import_store_key_params params
= { data
, NULL
, &size
};
43 if (CRYPT32_CALL( import_store_key
, ¶ms
) != STATUS_BUFFER_TOO_SMALL
) return 0;
45 acquire_flags
= (flags
& CRYPT_MACHINE_KEYSET
) | CRYPT_NEWKEYSET
;
46 if (!CryptAcquireContextW( &prov
, NULL
, MS_ENHANCED_PROV_W
, PROV_RSA_FULL
, acquire_flags
))
48 if (GetLastError() != NTE_EXISTS
) return 0;
50 acquire_flags
&= ~CRYPT_NEWKEYSET
;
51 if (!CryptAcquireContextW( &prov
, NULL
, MS_ENHANCED_PROV_W
, PROV_RSA_FULL
, acquire_flags
))
53 WARN( "CryptAcquireContextW failed %08x\n", GetLastError() );
58 params
.buf
= key
= malloc( size
);
59 if (CRYPT32_CALL( import_store_key
, ¶ms
) ||
60 !CryptImportKey( prov
, key
, size
, 0, flags
& CRYPT_EXPORTABLE
, &cryptkey
))
62 WARN( "CryptImportKey failed %08x\n", GetLastError() );
63 CryptReleaseContext( prov
, 0 );
67 CryptDestroyKey( cryptkey
);
72 static BOOL
set_key_context( const void *ctx
, HCRYPTPROV prov
)
74 CERT_KEY_CONTEXT key_ctx
;
75 key_ctx
.cbSize
= sizeof(key_ctx
);
76 key_ctx
.hCryptProv
= prov
;
77 key_ctx
.dwKeySpec
= AT_KEYEXCHANGE
;
78 return CertSetCertificateContextProperty( ctx
, CERT_KEY_CONTEXT_PROP_ID
, 0, &key_ctx
);
81 static WCHAR
*get_provider_property( HCRYPTPROV prov
, DWORD prop_id
, DWORD
*len
)
87 CryptGetProvParam( prov
, prop_id
, NULL
, &size
, 0 );
88 if (!size
) return NULL
;
89 if (!(str
= CryptMemAlloc( size
))) return NULL
;
90 CryptGetProvParam( prov
, prop_id
, (BYTE
*)str
, &size
, 0 );
92 *len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
93 if ((ret
= CryptMemAlloc( *len
* sizeof(WCHAR
) ))) MultiByteToWideChar( CP_ACP
, 0, str
, -1, ret
, *len
);
98 static BOOL
set_key_prov_info( const void *ctx
, HCRYPTPROV prov
)
100 CRYPT_KEY_PROV_INFO
*prov_info
;
101 DWORD size
, len_container
, len_name
;
102 WCHAR
*ptr
, *container
, *name
;
105 if (!(container
= get_provider_property( prov
, PP_CONTAINER
, &len_container
))) return FALSE
;
106 if (!(name
= get_provider_property( prov
, PP_NAME
, &len_name
)))
108 CryptMemFree( container
);
111 if (!(prov_info
= CryptMemAlloc( sizeof(*prov_info
) + (len_container
+ len_name
) * sizeof(WCHAR
) )))
113 CryptMemFree( container
);
114 CryptMemFree( name
);
118 ptr
= (WCHAR
*)(prov_info
+ 1);
119 prov_info
->pwszContainerName
= ptr
;
120 lstrcpyW( prov_info
->pwszContainerName
, container
);
122 ptr
+= len_container
;
123 prov_info
->pwszProvName
= ptr
;
124 lstrcpyW( prov_info
->pwszProvName
, name
);
126 size
= sizeof(prov_info
->dwProvType
);
127 CryptGetProvParam( prov
, PP_PROVTYPE
, (BYTE
*)&prov_info
->dwProvType
, &size
, 0 );
129 prov_info
->dwFlags
= 0;
130 prov_info
->cProvParam
= 0;
131 prov_info
->rgProvParam
= NULL
;
132 size
= sizeof(prov_info
->dwKeySpec
);
133 CryptGetProvParam( prov
, PP_KEYSPEC
, (BYTE
*)&prov_info
->dwKeySpec
, &size
, 0 );
135 ret
= CertSetCertificateContextProperty( ctx
, CERT_KEY_PROV_INFO_PROP_ID
, 0, prov_info
);
137 CryptMemFree( prov_info
);
138 CryptMemFree( name
);
139 CryptMemFree( container
);
143 HCERTSTORE WINAPI
PFXImportCertStore( CRYPT_DATA_BLOB
*pfx
, const WCHAR
*password
, DWORD flags
)
146 HCERTSTORE store
= NULL
;
148 struct cert_store_data
*data
= NULL
;
149 struct open_cert_store_params open_params
= { pfx
, password
, &data
};
150 struct close_cert_store_params close_params
;
154 SetLastError( ERROR_INVALID_PARAMETER
);
157 if (flags
& ~(CRYPT_EXPORTABLE
|CRYPT_USER_KEYSET
|CRYPT_MACHINE_KEYSET
|PKCS12_NO_PERSIST_KEY
))
159 FIXME( "flags %08x not supported\n", flags
);
162 if (CRYPT32_CALL( open_cert_store
, &open_params
)) return NULL
;
164 prov
= import_key( data
, flags
);
165 if (!prov
) goto error
;
167 if (!(store
= CertOpenStore( CERT_STORE_PROV_MEMORY
, 0, 0, 0, NULL
)))
169 WARN( "CertOpenStore failed %08x\n", GetLastError() );
175 const void *ctx
= NULL
;
177 struct import_store_cert_params import_params
= { data
, i
, NULL
, &size
};
179 if (CRYPT32_CALL( import_store_cert
, &import_params
) != STATUS_BUFFER_TOO_SMALL
) break;
180 import_params
.buf
= cert
= malloc( size
);
181 if (!CRYPT32_CALL( import_store_cert
, &import_params
))
182 ctx
= CertCreateContext( CERT_STORE_CERTIFICATE_CONTEXT
, X509_ASN_ENCODING
, cert
, size
, 0, NULL
);
186 WARN( "CertCreateContext failed %08x\n", GetLastError() );
189 if (flags
& PKCS12_NO_PERSIST_KEY
)
191 if (!set_key_context( ctx
, prov
))
193 WARN( "failed to set context property %08x\n", GetLastError() );
194 CertFreeCertificateContext( ctx
);
198 else if (!set_key_prov_info( ctx
, prov
))
200 WARN( "failed to set provider info property %08x\n", GetLastError() );
201 CertFreeCertificateContext( ctx
);
204 if (!CertAddCertificateContextToStore( store
, ctx
, CERT_STORE_ADD_ALWAYS
, NULL
))
206 WARN( "CertAddCertificateContextToStore failed %08x\n", GetLastError() );
207 CertFreeCertificateContext( ctx
);
210 CertFreeCertificateContext( ctx
);
213 close_params
.data
= data
;
214 CRYPT32_CALL( close_cert_store
, &close_params
);
218 CryptReleaseContext( prov
, 0 );
219 CertCloseStore( store
, 0 );
220 close_params
.data
= data
;
221 CRYPT32_CALL( close_cert_store
, &close_params
);
225 BOOL WINAPI
PFXVerifyPassword( CRYPT_DATA_BLOB
*pfx
, const WCHAR
*password
, DWORD flags
)
227 FIXME( "(%p, %p, %08x): stub\n", pfx
, password
, flags
);
231 BOOL WINAPI
PFXExportCertStore( HCERTSTORE store
, CRYPT_DATA_BLOB
*pfx
, const WCHAR
*password
, DWORD flags
)
233 return PFXExportCertStoreEx( store
, pfx
, password
, NULL
, flags
);
236 BOOL WINAPI
PFXExportCertStoreEx( HCERTSTORE store
, CRYPT_DATA_BLOB
*pfx
, const WCHAR
*password
, void *reserved
,
239 FIXME( "(%p, %p, %p, %p, %08x): stub\n", store
, pfx
, password
, reserved
, flags
);