xref: /freebsd/crypto/openssl/engines/e_capi.c (revision db522d3ae42d8f706499b4b4bc97836292ab180b)
1db522d3aSSimon L. B. Nielsen /* engines/e_capi.c */
2db522d3aSSimon L. B. Nielsen /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3db522d3aSSimon L. B. Nielsen  * project.
4db522d3aSSimon L. B. Nielsen  */
5db522d3aSSimon L. B. Nielsen /* ====================================================================
6db522d3aSSimon L. B. Nielsen  * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
7db522d3aSSimon L. B. Nielsen  *
8db522d3aSSimon L. B. Nielsen  * Redistribution and use in source and binary forms, with or without
9db522d3aSSimon L. B. Nielsen  * modification, are permitted provided that the following conditions
10db522d3aSSimon L. B. Nielsen  * are met:
11db522d3aSSimon L. B. Nielsen  *
12db522d3aSSimon L. B. Nielsen  * 1. Redistributions of source code must retain the above copyright
13db522d3aSSimon L. B. Nielsen  *    notice, this list of conditions and the following disclaimer.
14db522d3aSSimon L. B. Nielsen  *
15db522d3aSSimon L. B. Nielsen  * 2. Redistributions in binary form must reproduce the above copyright
16db522d3aSSimon L. B. Nielsen  *    notice, this list of conditions and the following disclaimer in
17db522d3aSSimon L. B. Nielsen  *    the documentation and/or other materials provided with the
18db522d3aSSimon L. B. Nielsen  *    distribution.
19db522d3aSSimon L. B. Nielsen  *
20db522d3aSSimon L. B. Nielsen  * 3. All advertising materials mentioning features or use of this
21db522d3aSSimon L. B. Nielsen  *    software must display the following acknowledgment:
22db522d3aSSimon L. B. Nielsen  *    "This product includes software developed by the OpenSSL Project
23db522d3aSSimon L. B. Nielsen  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24db522d3aSSimon L. B. Nielsen  *
25db522d3aSSimon L. B. Nielsen  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26db522d3aSSimon L. B. Nielsen  *    endorse or promote products derived from this software without
27db522d3aSSimon L. B. Nielsen  *    prior written permission. For written permission, please contact
28db522d3aSSimon L. B. Nielsen  *    licensing@OpenSSL.org.
29db522d3aSSimon L. B. Nielsen  *
30db522d3aSSimon L. B. Nielsen  * 5. Products derived from this software may not be called "OpenSSL"
31db522d3aSSimon L. B. Nielsen  *    nor may "OpenSSL" appear in their names without prior written
32db522d3aSSimon L. B. Nielsen  *    permission of the OpenSSL Project.
33db522d3aSSimon L. B. Nielsen  *
34db522d3aSSimon L. B. Nielsen  * 6. Redistributions of any form whatsoever must retain the following
35db522d3aSSimon L. B. Nielsen  *    acknowledgment:
36db522d3aSSimon L. B. Nielsen  *    "This product includes software developed by the OpenSSL Project
37db522d3aSSimon L. B. Nielsen  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38db522d3aSSimon L. B. Nielsen  *
39db522d3aSSimon L. B. Nielsen  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40db522d3aSSimon L. B. Nielsen  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41db522d3aSSimon L. B. Nielsen  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42db522d3aSSimon L. B. Nielsen  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43db522d3aSSimon L. B. Nielsen  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44db522d3aSSimon L. B. Nielsen  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45db522d3aSSimon L. B. Nielsen  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46db522d3aSSimon L. B. Nielsen  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47db522d3aSSimon L. B. Nielsen  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48db522d3aSSimon L. B. Nielsen  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49db522d3aSSimon L. B. Nielsen  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50db522d3aSSimon L. B. Nielsen  * OF THE POSSIBILITY OF SUCH DAMAGE.
51db522d3aSSimon L. B. Nielsen  * ====================================================================
52db522d3aSSimon L. B. Nielsen  */
53db522d3aSSimon L. B. Nielsen 
54db522d3aSSimon L. B. Nielsen 
55db522d3aSSimon L. B. Nielsen #include <stdio.h>
56db522d3aSSimon L. B. Nielsen #include <string.h>
57db522d3aSSimon L. B. Nielsen #include <openssl/crypto.h>
58db522d3aSSimon L. B. Nielsen #include <openssl/buffer.h>
59db522d3aSSimon L. B. Nielsen #include <openssl/rsa.h>
60db522d3aSSimon L. B. Nielsen #include <openssl/bn.h>
61db522d3aSSimon L. B. Nielsen 
62db522d3aSSimon L. B. Nielsen #ifdef OPENSSL_SYS_WIN32
63db522d3aSSimon L. B. Nielsen #ifndef OPENSSL_NO_CAPIENG
64db522d3aSSimon L. B. Nielsen 
65db522d3aSSimon L. B. Nielsen 
66db522d3aSSimon L. B. Nielsen #include <windows.h>
67db522d3aSSimon L. B. Nielsen 
68db522d3aSSimon L. B. Nielsen #ifndef _WIN32_WINNT
69db522d3aSSimon L. B. Nielsen #define _WIN32_WINNT 0x0400
70db522d3aSSimon L. B. Nielsen #endif
71db522d3aSSimon L. B. Nielsen 
72db522d3aSSimon L. B. Nielsen #include <wincrypt.h>
73db522d3aSSimon L. B. Nielsen 
74db522d3aSSimon L. B. Nielsen #undef X509_EXTENSIONS
75db522d3aSSimon L. B. Nielsen #undef X509_CERT_PAIR
76db522d3aSSimon L. B. Nielsen 
77db522d3aSSimon L. B. Nielsen /* Definitions which may be missing from earlier version of headers */
78db522d3aSSimon L. B. Nielsen #ifndef CERT_STORE_OPEN_EXISTING_FLAG
79db522d3aSSimon L. B. Nielsen #define CERT_STORE_OPEN_EXISTING_FLAG                   0x00004000
80db522d3aSSimon L. B. Nielsen #endif
81db522d3aSSimon L. B. Nielsen 
82db522d3aSSimon L. B. Nielsen #ifndef CERT_STORE_CREATE_NEW_FLAG
83db522d3aSSimon L. B. Nielsen #define CERT_STORE_CREATE_NEW_FLAG                      0x00002000
84db522d3aSSimon L. B. Nielsen #endif
85db522d3aSSimon L. B. Nielsen 
86db522d3aSSimon L. B. Nielsen #include <openssl/engine.h>
87db522d3aSSimon L. B. Nielsen #include <openssl/pem.h>
88db522d3aSSimon L. B. Nielsen #include <openssl/x509v3.h>
89db522d3aSSimon L. B. Nielsen 
90db522d3aSSimon L. B. Nielsen #include "e_capi_err.h"
91db522d3aSSimon L. B. Nielsen #include "e_capi_err.c"
92db522d3aSSimon L. B. Nielsen 
93db522d3aSSimon L. B. Nielsen 
94db522d3aSSimon L. B. Nielsen static const char *engine_capi_id = "capi";
95db522d3aSSimon L. B. Nielsen static const char *engine_capi_name = "CryptoAPI ENGINE";
96db522d3aSSimon L. B. Nielsen 
97db522d3aSSimon L. B. Nielsen typedef struct CAPI_CTX_st CAPI_CTX;
98db522d3aSSimon L. B. Nielsen typedef struct CAPI_KEY_st CAPI_KEY;
99db522d3aSSimon L. B. Nielsen 
100db522d3aSSimon L. B. Nielsen static void capi_addlasterror(void);
101db522d3aSSimon L. B. Nielsen static void capi_adderror(DWORD err);
102db522d3aSSimon L. B. Nielsen 
103db522d3aSSimon L. B. Nielsen static void CAPI_trace(CAPI_CTX *ctx, char *format, ...);
104db522d3aSSimon L. B. Nielsen 
105db522d3aSSimon L. B. Nielsen static int capi_list_providers(CAPI_CTX *ctx, BIO *out);
106db522d3aSSimon L. B. Nielsen static int capi_list_containers(CAPI_CTX *ctx, BIO *out);
107db522d3aSSimon L. B. Nielsen int capi_list_certs(CAPI_CTX *ctx, BIO *out, char *storename);
108db522d3aSSimon L. B. Nielsen void capi_free_key(CAPI_KEY *key);
109db522d3aSSimon L. B. Nielsen 
110db522d3aSSimon L. B. Nielsen static PCCERT_CONTEXT capi_find_cert(CAPI_CTX *ctx, const char *id, HCERTSTORE hstore);
111db522d3aSSimon L. B. Nielsen 
112db522d3aSSimon L. B. Nielsen CAPI_KEY *capi_find_key(CAPI_CTX *ctx, const char *id);
113db522d3aSSimon L. B. Nielsen 
114db522d3aSSimon L. B. Nielsen static EVP_PKEY *capi_load_privkey(ENGINE *eng, const char *key_id,
115db522d3aSSimon L. B. Nielsen 	UI_METHOD *ui_method, void *callback_data);
116db522d3aSSimon L. B. Nielsen static int capi_rsa_sign(int dtype, const unsigned char *m, unsigned int m_len,
117db522d3aSSimon L. B. Nielsen              unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
118db522d3aSSimon L. B. Nielsen static int capi_rsa_priv_enc(int flen, const unsigned char *from,
119db522d3aSSimon L. B. Nielsen                 unsigned char *to, RSA *rsa, int padding);
120db522d3aSSimon L. B. Nielsen static int capi_rsa_priv_dec(int flen, const unsigned char *from,
121db522d3aSSimon L. B. Nielsen                 unsigned char *to, RSA *rsa, int padding);
122db522d3aSSimon L. B. Nielsen static int capi_rsa_free(RSA *rsa);
123db522d3aSSimon L. B. Nielsen 
124db522d3aSSimon L. B. Nielsen static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen,
125db522d3aSSimon L. B. Nielsen 							DSA *dsa);
126db522d3aSSimon L. B. Nielsen static int capi_dsa_free(DSA *dsa);
127db522d3aSSimon L. B. Nielsen 
128db522d3aSSimon L. B. Nielsen static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl,
129db522d3aSSimon L. B. Nielsen 	STACK_OF(X509_NAME) *ca_dn, X509 **pcert, EVP_PKEY **pkey,
130db522d3aSSimon L. B. Nielsen 	STACK_OF(X509) **pother, UI_METHOD *ui_method, void *callback_data);
131db522d3aSSimon L. B. Nielsen 
132db522d3aSSimon L. B. Nielsen static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
133db522d3aSSimon L. B. Nielsen #ifdef OPENSSL_CAPIENG_DIALOG
134db522d3aSSimon L. B. Nielsen static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
135db522d3aSSimon L. B. Nielsen #endif
136db522d3aSSimon L. B. Nielsen 
137db522d3aSSimon L. B. Nielsen typedef PCCERT_CONTEXT (WINAPI *CERTDLG)(HCERTSTORE, HWND, LPCWSTR,
138db522d3aSSimon L. B. Nielsen 						LPCWSTR, DWORD, DWORD,
139db522d3aSSimon L. B. Nielsen 						void *);
140db522d3aSSimon L. B. Nielsen typedef HWND (WINAPI *GETCONSWIN)(void);
141db522d3aSSimon L. B. Nielsen 
142db522d3aSSimon L. B. Nielsen /* This structure contains CAPI ENGINE specific data:
143db522d3aSSimon L. B. Nielsen  * it contains various global options and affects how
144db522d3aSSimon L. B. Nielsen  * other functions behave.
145db522d3aSSimon L. B. Nielsen  */
146db522d3aSSimon L. B. Nielsen 
147db522d3aSSimon L. B. Nielsen #define CAPI_DBG_TRACE	2
148db522d3aSSimon L. B. Nielsen #define CAPI_DBG_ERROR	1
149db522d3aSSimon L. B. Nielsen 
150db522d3aSSimon L. B. Nielsen struct CAPI_CTX_st {
151db522d3aSSimon L. B. Nielsen 	int debug_level;
152db522d3aSSimon L. B. Nielsen 	char *debug_file;
153db522d3aSSimon L. B. Nielsen 	/* Parameters to use for container lookup */
154db522d3aSSimon L. B. Nielsen 	DWORD keytype;
155db522d3aSSimon L. B. Nielsen 	LPTSTR cspname;
156db522d3aSSimon L. B. Nielsen 	DWORD csptype;
157db522d3aSSimon L. B. Nielsen 	/* Certificate store name to use */
158db522d3aSSimon L. B. Nielsen 	LPTSTR storename;
159db522d3aSSimon L. B. Nielsen 	LPTSTR ssl_client_store;
160db522d3aSSimon L. B. Nielsen 	/* System store flags */
161db522d3aSSimon L. B. Nielsen 	DWORD store_flags;
162db522d3aSSimon L. B. Nielsen 
163db522d3aSSimon L. B. Nielsen /* Lookup string meanings in load_private_key */
164db522d3aSSimon L. B. Nielsen /* Substring of subject: uses "storename" */
165db522d3aSSimon L. B. Nielsen #define CAPI_LU_SUBSTR		0
166db522d3aSSimon L. B. Nielsen /* Friendly name: uses storename */
167db522d3aSSimon L. B. Nielsen #define CAPI_LU_FNAME		1
168db522d3aSSimon L. B. Nielsen /* Container name: uses cspname, keytype */
169db522d3aSSimon L. B. Nielsen #define CAPI_LU_CONTNAME	2
170db522d3aSSimon L. B. Nielsen 	int lookup_method;
171db522d3aSSimon L. B. Nielsen /* Info to dump with dumpcerts option */
172db522d3aSSimon L. B. Nielsen /* Issuer and serial name strings */
173db522d3aSSimon L. B. Nielsen #define CAPI_DMP_SUMMARY	0x1
174db522d3aSSimon L. B. Nielsen /* Friendly name */
175db522d3aSSimon L. B. Nielsen #define CAPI_DMP_FNAME		0x2
176db522d3aSSimon L. B. Nielsen /* Full X509_print dump */
177db522d3aSSimon L. B. Nielsen #define CAPI_DMP_FULL		0x4
178db522d3aSSimon L. B. Nielsen /* Dump PEM format certificate */
179db522d3aSSimon L. B. Nielsen #define CAPI_DMP_PEM		0x8
180db522d3aSSimon L. B. Nielsen /* Dump pseudo key (if possible) */
181db522d3aSSimon L. B. Nielsen #define CAPI_DMP_PSKEY		0x10
182db522d3aSSimon L. B. Nielsen /* Dump key info (if possible) */
183db522d3aSSimon L. B. Nielsen #define CAPI_DMP_PKEYINFO	0x20
184db522d3aSSimon L. B. Nielsen 
185db522d3aSSimon L. B. Nielsen 	DWORD dump_flags;
186db522d3aSSimon L. B. Nielsen 	int (*client_cert_select)(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
187db522d3aSSimon L. B. Nielsen 
188db522d3aSSimon L. B. Nielsen 	CERTDLG certselectdlg;
189db522d3aSSimon L. B. Nielsen 	GETCONSWIN getconswindow;
190db522d3aSSimon L. B. Nielsen };
191db522d3aSSimon L. B. Nielsen 
192db522d3aSSimon L. B. Nielsen 
193db522d3aSSimon L. B. Nielsen static CAPI_CTX *capi_ctx_new();
194db522d3aSSimon L. B. Nielsen static void capi_ctx_free(CAPI_CTX *ctx);
195db522d3aSSimon L. B. Nielsen static int capi_ctx_set_provname(CAPI_CTX *ctx, LPSTR pname, DWORD type, int check);
196db522d3aSSimon L. B. Nielsen static int capi_ctx_set_provname_idx(CAPI_CTX *ctx, int idx);
197db522d3aSSimon L. B. Nielsen 
198db522d3aSSimon L. B. Nielsen #define CAPI_CMD_LIST_CERTS		ENGINE_CMD_BASE
199db522d3aSSimon L. B. Nielsen #define CAPI_CMD_LOOKUP_CERT		(ENGINE_CMD_BASE + 1)
200db522d3aSSimon L. B. Nielsen #define CAPI_CMD_DEBUG_LEVEL		(ENGINE_CMD_BASE + 2)
201db522d3aSSimon L. B. Nielsen #define CAPI_CMD_DEBUG_FILE		(ENGINE_CMD_BASE + 3)
202db522d3aSSimon L. B. Nielsen #define CAPI_CMD_KEYTYPE		(ENGINE_CMD_BASE + 4)
203db522d3aSSimon L. B. Nielsen #define CAPI_CMD_LIST_CSPS		(ENGINE_CMD_BASE + 5)
204db522d3aSSimon L. B. Nielsen #define CAPI_CMD_SET_CSP_IDX		(ENGINE_CMD_BASE + 6)
205db522d3aSSimon L. B. Nielsen #define CAPI_CMD_SET_CSP_NAME		(ENGINE_CMD_BASE + 7)
206db522d3aSSimon L. B. Nielsen #define CAPI_CMD_SET_CSP_TYPE		(ENGINE_CMD_BASE + 8)
207db522d3aSSimon L. B. Nielsen #define CAPI_CMD_LIST_CONTAINERS	(ENGINE_CMD_BASE + 9)
208db522d3aSSimon L. B. Nielsen #define CAPI_CMD_LIST_OPTIONS		(ENGINE_CMD_BASE + 10)
209db522d3aSSimon L. B. Nielsen #define CAPI_CMD_LOOKUP_METHOD		(ENGINE_CMD_BASE + 11)
210db522d3aSSimon L. B. Nielsen #define CAPI_CMD_STORE_NAME		(ENGINE_CMD_BASE + 12)
211db522d3aSSimon L. B. Nielsen #define CAPI_CMD_STORE_FLAGS		(ENGINE_CMD_BASE + 13)
212db522d3aSSimon L. B. Nielsen 
213db522d3aSSimon L. B. Nielsen static const ENGINE_CMD_DEFN capi_cmd_defns[] = {
214db522d3aSSimon L. B. Nielsen 	{CAPI_CMD_LIST_CERTS,
215db522d3aSSimon L. B. Nielsen 		"list_certs",
216db522d3aSSimon L. B. Nielsen 		"List all certificates in store",
217db522d3aSSimon L. B. Nielsen 		ENGINE_CMD_FLAG_NO_INPUT},
218db522d3aSSimon L. B. Nielsen 	{CAPI_CMD_LOOKUP_CERT,
219db522d3aSSimon L. B. Nielsen 		"lookup_cert",
220db522d3aSSimon L. B. Nielsen 		"Lookup and output certificates",
221db522d3aSSimon L. B. Nielsen 		ENGINE_CMD_FLAG_STRING},
222db522d3aSSimon L. B. Nielsen 	{CAPI_CMD_DEBUG_LEVEL,
223db522d3aSSimon L. B. Nielsen 		"debug_level",
224db522d3aSSimon L. B. Nielsen 		"debug level (1=errors, 2=trace)",
225db522d3aSSimon L. B. Nielsen 		ENGINE_CMD_FLAG_NUMERIC},
226db522d3aSSimon L. B. Nielsen 	{CAPI_CMD_DEBUG_FILE,
227db522d3aSSimon L. B. Nielsen 		"debug_file",
228db522d3aSSimon L. B. Nielsen 		"debugging filename)",
229db522d3aSSimon L. B. Nielsen 		ENGINE_CMD_FLAG_STRING},
230db522d3aSSimon L. B. Nielsen 	{CAPI_CMD_KEYTYPE,
231db522d3aSSimon L. B. Nielsen 		"key_type",
232db522d3aSSimon L. B. Nielsen 		"Key type: 1=AT_KEYEXCHANGE (default), 2=AT_SIGNATURE",
233db522d3aSSimon L. B. Nielsen 		ENGINE_CMD_FLAG_NUMERIC},
234db522d3aSSimon L. B. Nielsen 	{CAPI_CMD_LIST_CSPS,
235db522d3aSSimon L. B. Nielsen 		"list_csps",
236db522d3aSSimon L. B. Nielsen 		"List all CSPs",
237db522d3aSSimon L. B. Nielsen 		ENGINE_CMD_FLAG_NO_INPUT},
238db522d3aSSimon L. B. Nielsen 	{CAPI_CMD_SET_CSP_IDX,
239db522d3aSSimon L. B. Nielsen 		"csp_idx",
240db522d3aSSimon L. B. Nielsen 		"Set CSP by index",
241db522d3aSSimon L. B. Nielsen 		ENGINE_CMD_FLAG_NUMERIC},
242db522d3aSSimon L. B. Nielsen 	{CAPI_CMD_SET_CSP_NAME,
243db522d3aSSimon L. B. Nielsen 		"csp_name",
244db522d3aSSimon L. B. Nielsen 		"Set CSP name, (default CSP used if not specified)",
245db522d3aSSimon L. B. Nielsen 		ENGINE_CMD_FLAG_STRING},
246db522d3aSSimon L. B. Nielsen 	{CAPI_CMD_SET_CSP_TYPE,
247db522d3aSSimon L. B. Nielsen 		"csp_type",
248db522d3aSSimon L. B. Nielsen 		"Set CSP type, (default RSA_PROV_FULL)",
249db522d3aSSimon L. B. Nielsen 		ENGINE_CMD_FLAG_NUMERIC},
250db522d3aSSimon L. B. Nielsen 	{CAPI_CMD_LIST_CONTAINERS,
251db522d3aSSimon L. B. Nielsen 		"list_containers",
252db522d3aSSimon L. B. Nielsen 		"list container names",
253db522d3aSSimon L. B. Nielsen 		ENGINE_CMD_FLAG_NO_INPUT},
254db522d3aSSimon L. B. Nielsen 	{CAPI_CMD_LIST_OPTIONS,
255db522d3aSSimon L. B. Nielsen 		"list_options",
256db522d3aSSimon L. B. Nielsen 		"Set list options (1=summary,2=friendly name, 4=full printout, 8=PEM output, 16=XXX, "
257db522d3aSSimon L. B. Nielsen 		"32=private key info)",
258db522d3aSSimon L. B. Nielsen 		ENGINE_CMD_FLAG_NUMERIC},
259db522d3aSSimon L. B. Nielsen 	{CAPI_CMD_LOOKUP_METHOD,
260db522d3aSSimon L. B. Nielsen 		"lookup_method",
261db522d3aSSimon L. B. Nielsen 		"Set key lookup method (1=substring, 2=friendlyname, 3=container name)",
262db522d3aSSimon L. B. Nielsen 		ENGINE_CMD_FLAG_NUMERIC},
263db522d3aSSimon L. B. Nielsen 	{CAPI_CMD_STORE_NAME,
264db522d3aSSimon L. B. Nielsen 		"store_name",
265db522d3aSSimon L. B. Nielsen 		"certificate store name, default \"MY\"",
266db522d3aSSimon L. B. Nielsen 		ENGINE_CMD_FLAG_STRING},
267db522d3aSSimon L. B. Nielsen 	{CAPI_CMD_STORE_FLAGS,
268db522d3aSSimon L. B. Nielsen 		"store_flags",
269db522d3aSSimon L. B. Nielsen 		"Certificate store flags: 1 = system store",
270db522d3aSSimon L. B. Nielsen 		ENGINE_CMD_FLAG_NUMERIC},
271db522d3aSSimon L. B. Nielsen 
272db522d3aSSimon L. B. Nielsen 	{0, NULL, NULL, 0}
273db522d3aSSimon L. B. Nielsen 	};
274db522d3aSSimon L. B. Nielsen 
275db522d3aSSimon L. B. Nielsen static int capi_idx = -1;
276db522d3aSSimon L. B. Nielsen static int rsa_capi_idx = -1;
277db522d3aSSimon L. B. Nielsen static int dsa_capi_idx = -1;
278db522d3aSSimon L. B. Nielsen static int cert_capi_idx = -1;
279db522d3aSSimon L. B. Nielsen 
280db522d3aSSimon L. B. Nielsen static int capi_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
281db522d3aSSimon L. B. Nielsen 	{
282db522d3aSSimon L. B. Nielsen 	int ret = 1;
283db522d3aSSimon L. B. Nielsen 	CAPI_CTX *ctx;
284db522d3aSSimon L. B. Nielsen 	BIO *out;
285db522d3aSSimon L. B. Nielsen 	if (capi_idx == -1)
286db522d3aSSimon L. B. Nielsen 		{
287db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_ENGINE_NOT_INITIALIZED);
288db522d3aSSimon L. B. Nielsen 		return 0;
289db522d3aSSimon L. B. Nielsen 		}
290db522d3aSSimon L. B. Nielsen 	ctx = ENGINE_get_ex_data(e, capi_idx);
291db522d3aSSimon L. B. Nielsen 	out = BIO_new_fp(stdout, BIO_NOCLOSE);
292db522d3aSSimon L. B. Nielsen 	switch (cmd)
293db522d3aSSimon L. B. Nielsen 		{
294db522d3aSSimon L. B. Nielsen 		case CAPI_CMD_LIST_CSPS:
295db522d3aSSimon L. B. Nielsen 		ret = capi_list_providers(ctx, out);
296db522d3aSSimon L. B. Nielsen 		break;
297db522d3aSSimon L. B. Nielsen 
298db522d3aSSimon L. B. Nielsen 		case CAPI_CMD_LIST_CERTS:
299db522d3aSSimon L. B. Nielsen 		ret = capi_list_certs(ctx, out, NULL);
300db522d3aSSimon L. B. Nielsen 		break;
301db522d3aSSimon L. B. Nielsen 
302db522d3aSSimon L. B. Nielsen 		case CAPI_CMD_LOOKUP_CERT:
303db522d3aSSimon L. B. Nielsen 		ret = capi_list_certs(ctx, out, p);
304db522d3aSSimon L. B. Nielsen 		break;
305db522d3aSSimon L. B. Nielsen 
306db522d3aSSimon L. B. Nielsen 		case CAPI_CMD_LIST_CONTAINERS:
307db522d3aSSimon L. B. Nielsen 		ret = capi_list_containers(ctx, out);
308db522d3aSSimon L. B. Nielsen 		break;
309db522d3aSSimon L. B. Nielsen 
310db522d3aSSimon L. B. Nielsen 		case CAPI_CMD_STORE_NAME:
311db522d3aSSimon L. B. Nielsen 		if (ctx->storename)
312db522d3aSSimon L. B. Nielsen 			OPENSSL_free(ctx->storename);
313db522d3aSSimon L. B. Nielsen 		ctx->storename = BUF_strdup(p);
314db522d3aSSimon L. B. Nielsen 		CAPI_trace(ctx, "Setting store name to %s\n", p);
315db522d3aSSimon L. B. Nielsen 		break;
316db522d3aSSimon L. B. Nielsen 
317db522d3aSSimon L. B. Nielsen 		case CAPI_CMD_STORE_FLAGS:
318db522d3aSSimon L. B. Nielsen 		if (i & 1)
319db522d3aSSimon L. B. Nielsen 			{
320db522d3aSSimon L. B. Nielsen 			ctx->store_flags |= CERT_SYSTEM_STORE_LOCAL_MACHINE;
321db522d3aSSimon L. B. Nielsen 			ctx->store_flags &= ~CERT_SYSTEM_STORE_CURRENT_USER;
322db522d3aSSimon L. B. Nielsen 			}
323db522d3aSSimon L. B. Nielsen 		else
324db522d3aSSimon L. B. Nielsen 			{
325db522d3aSSimon L. B. Nielsen 			ctx->store_flags |= CERT_SYSTEM_STORE_CURRENT_USER;
326db522d3aSSimon L. B. Nielsen 			ctx->store_flags &= ~CERT_SYSTEM_STORE_LOCAL_MACHINE;
327db522d3aSSimon L. B. Nielsen 			}
328db522d3aSSimon L. B. Nielsen 		CAPI_trace(ctx, "Setting flags to %d\n", i);
329db522d3aSSimon L. B. Nielsen 		break;
330db522d3aSSimon L. B. Nielsen 
331db522d3aSSimon L. B. Nielsen 		case CAPI_CMD_DEBUG_LEVEL:
332db522d3aSSimon L. B. Nielsen 		ctx->debug_level = (int)i;
333db522d3aSSimon L. B. Nielsen 		CAPI_trace(ctx, "Setting debug level to %d\n", ctx->debug_level);
334db522d3aSSimon L. B. Nielsen 		break;
335db522d3aSSimon L. B. Nielsen 
336db522d3aSSimon L. B. Nielsen 		case CAPI_CMD_DEBUG_FILE:
337db522d3aSSimon L. B. Nielsen 		ctx->debug_file = BUF_strdup(p);
338db522d3aSSimon L. B. Nielsen 		CAPI_trace(ctx, "Setting debug file to %s\n", ctx->debug_file);
339db522d3aSSimon L. B. Nielsen 		break;
340db522d3aSSimon L. B. Nielsen 
341db522d3aSSimon L. B. Nielsen 		case CAPI_CMD_KEYTYPE:
342db522d3aSSimon L. B. Nielsen 		ctx->keytype = i;
343db522d3aSSimon L. B. Nielsen 		CAPI_trace(ctx, "Setting key type to %d\n", ctx->keytype);
344db522d3aSSimon L. B. Nielsen 		break;
345db522d3aSSimon L. B. Nielsen 
346db522d3aSSimon L. B. Nielsen 		case CAPI_CMD_SET_CSP_IDX:
347db522d3aSSimon L. B. Nielsen 		ret = capi_ctx_set_provname_idx(ctx, i);
348db522d3aSSimon L. B. Nielsen 		break;
349db522d3aSSimon L. B. Nielsen 
350db522d3aSSimon L. B. Nielsen 		case CAPI_CMD_LIST_OPTIONS:
351db522d3aSSimon L. B. Nielsen 		ctx->dump_flags = i;
352db522d3aSSimon L. B. Nielsen 		break;
353db522d3aSSimon L. B. Nielsen 
354db522d3aSSimon L. B. Nielsen 		case CAPI_CMD_LOOKUP_METHOD:
355db522d3aSSimon L. B. Nielsen 		if (i < 1 || i > 3)
356db522d3aSSimon L. B. Nielsen 			{
357db522d3aSSimon L. B. Nielsen 			CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_INVALID_LOOKUP_METHOD);
358db522d3aSSimon L. B. Nielsen 			return 0;
359db522d3aSSimon L. B. Nielsen 			}
360db522d3aSSimon L. B. Nielsen 		ctx->lookup_method = i;
361db522d3aSSimon L. B. Nielsen 		break;
362db522d3aSSimon L. B. Nielsen 
363db522d3aSSimon L. B. Nielsen 		case CAPI_CMD_SET_CSP_NAME:
364db522d3aSSimon L. B. Nielsen 		ret = capi_ctx_set_provname(ctx, p, ctx->csptype, 1);
365db522d3aSSimon L. B. Nielsen 		break;
366db522d3aSSimon L. B. Nielsen 
367db522d3aSSimon L. B. Nielsen 		case CAPI_CMD_SET_CSP_TYPE:
368db522d3aSSimon L. B. Nielsen 		ctx->csptype = i;
369db522d3aSSimon L. B. Nielsen 		break;
370db522d3aSSimon L. B. Nielsen 
371db522d3aSSimon L. B. Nielsen 		default:
372db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_UNKNOWN_COMMAND);
373db522d3aSSimon L. B. Nielsen 		ret = 0;
374db522d3aSSimon L. B. Nielsen 	}
375db522d3aSSimon L. B. Nielsen 
376db522d3aSSimon L. B. Nielsen 	BIO_free(out);
377db522d3aSSimon L. B. Nielsen 	return ret;
378db522d3aSSimon L. B. Nielsen 
379db522d3aSSimon L. B. Nielsen 	}
380db522d3aSSimon L. B. Nielsen 
381db522d3aSSimon L. B. Nielsen static RSA_METHOD capi_rsa_method =
382db522d3aSSimon L. B. Nielsen 	{
383db522d3aSSimon L. B. Nielsen 	"CryptoAPI RSA method",
384db522d3aSSimon L. B. Nielsen 	0,				/* pub_enc */
385db522d3aSSimon L. B. Nielsen 	0,				/* pub_dec */
386db522d3aSSimon L. B. Nielsen 	capi_rsa_priv_enc,		/* priv_enc */
387db522d3aSSimon L. B. Nielsen 	capi_rsa_priv_dec,		/* priv_dec */
388db522d3aSSimon L. B. Nielsen 	0,				/* rsa_mod_exp */
389db522d3aSSimon L. B. Nielsen 	0,				/* bn_mod_exp */
390db522d3aSSimon L. B. Nielsen 	0,				/* init	*/
391db522d3aSSimon L. B. Nielsen 	capi_rsa_free,			/* finish */
392db522d3aSSimon L. B. Nielsen 	RSA_FLAG_SIGN_VER, 		/* flags */
393db522d3aSSimon L. B. Nielsen 	NULL,				/* app_data */
394db522d3aSSimon L. B. Nielsen 	capi_rsa_sign,			/* rsa_sign */
395db522d3aSSimon L. B. Nielsen 	0				/* rsa_verify */
396db522d3aSSimon L. B. Nielsen 	};
397db522d3aSSimon L. B. Nielsen 
398db522d3aSSimon L. B. Nielsen static DSA_METHOD capi_dsa_method =
399db522d3aSSimon L. B. Nielsen 	{
400db522d3aSSimon L. B. Nielsen 	"CryptoAPI DSA method",
401db522d3aSSimon L. B. Nielsen 	capi_dsa_do_sign,		/* dsa_do_sign */
402db522d3aSSimon L. B. Nielsen 	0,				/* dsa_sign_setup */
403db522d3aSSimon L. B. Nielsen 	0,				/* dsa_do_verify */
404db522d3aSSimon L. B. Nielsen 	0,				/* dsa_mod_exp */
405db522d3aSSimon L. B. Nielsen 	0,				/* bn_mod_exp */
406db522d3aSSimon L. B. Nielsen 	0,				/* init	*/
407db522d3aSSimon L. B. Nielsen 	capi_dsa_free,			/* finish */
408db522d3aSSimon L. B. Nielsen 	0, 				/* flags */
409db522d3aSSimon L. B. Nielsen 	NULL,				/* app_data */
410db522d3aSSimon L. B. Nielsen 	0,				/* dsa_paramgen */
411db522d3aSSimon L. B. Nielsen 	0				/* dsa_keygen */
412db522d3aSSimon L. B. Nielsen 	};
413db522d3aSSimon L. B. Nielsen 
414db522d3aSSimon L. B. Nielsen static int capi_init(ENGINE *e)
415db522d3aSSimon L. B. Nielsen 	{
416db522d3aSSimon L. B. Nielsen 	CAPI_CTX *ctx;
417db522d3aSSimon L. B. Nielsen 	const RSA_METHOD *ossl_rsa_meth;
418db522d3aSSimon L. B. Nielsen 	const DSA_METHOD *ossl_dsa_meth;
419db522d3aSSimon L. B. Nielsen 	capi_idx = ENGINE_get_ex_new_index(0, NULL, NULL, NULL, 0);
420db522d3aSSimon L. B. Nielsen 	cert_capi_idx = X509_get_ex_new_index(0, NULL, NULL, NULL, 0);
421db522d3aSSimon L. B. Nielsen 
422db522d3aSSimon L. B. Nielsen 	ctx = capi_ctx_new();
423db522d3aSSimon L. B. Nielsen 	if (!ctx || (capi_idx < 0))
424db522d3aSSimon L. B. Nielsen 		goto memerr;
425db522d3aSSimon L. B. Nielsen 
426db522d3aSSimon L. B. Nielsen 	ENGINE_set_ex_data(e, capi_idx, ctx);
427db522d3aSSimon L. B. Nielsen 	/* Setup RSA_METHOD */
428db522d3aSSimon L. B. Nielsen 	rsa_capi_idx = RSA_get_ex_new_index(0, NULL, NULL, NULL, 0);
429db522d3aSSimon L. B. Nielsen 	ossl_rsa_meth = RSA_PKCS1_SSLeay();
430db522d3aSSimon L. B. Nielsen 	capi_rsa_method.rsa_pub_enc = ossl_rsa_meth->rsa_pub_enc;
431db522d3aSSimon L. B. Nielsen 	capi_rsa_method.rsa_pub_dec = ossl_rsa_meth->rsa_pub_dec;
432db522d3aSSimon L. B. Nielsen 	capi_rsa_method.rsa_mod_exp = ossl_rsa_meth->rsa_mod_exp;
433db522d3aSSimon L. B. Nielsen 	capi_rsa_method.bn_mod_exp = ossl_rsa_meth->bn_mod_exp;
434db522d3aSSimon L. B. Nielsen 
435db522d3aSSimon L. B. Nielsen 	/* Setup DSA Method */
436db522d3aSSimon L. B. Nielsen 	dsa_capi_idx = DSA_get_ex_new_index(0, NULL, NULL, NULL, 0);
437db522d3aSSimon L. B. Nielsen 	ossl_dsa_meth = DSA_OpenSSL();
438db522d3aSSimon L. B. Nielsen 	capi_dsa_method.dsa_do_verify = ossl_dsa_meth->dsa_do_verify;
439db522d3aSSimon L. B. Nielsen 	capi_dsa_method.dsa_mod_exp = ossl_dsa_meth->dsa_mod_exp;
440db522d3aSSimon L. B. Nielsen 	capi_dsa_method.bn_mod_exp = ossl_dsa_meth->bn_mod_exp;
441db522d3aSSimon L. B. Nielsen 
442db522d3aSSimon L. B. Nielsen #ifdef OPENSSL_CAPIENG_DIALOG
443db522d3aSSimon L. B. Nielsen 	{
444db522d3aSSimon L. B. Nielsen 	HMODULE cryptui = LoadLibrary(TEXT("CRYPTUI.DLL"));
445db522d3aSSimon L. B. Nielsen 	HMODULE kernel = LoadLibrary(TEXT("KERNEL32.DLL"));
446db522d3aSSimon L. B. Nielsen 	if (cryptui)
447db522d3aSSimon L. B. Nielsen 		ctx->certselectdlg = (CERTDLG)GetProcAddress(cryptui, "CryptUIDlgSelectCertificateFromStore");
448db522d3aSSimon L. B. Nielsen 	if (kernel)
449db522d3aSSimon L. B. Nielsen 		ctx->getconswindow = (GETCONSWIN)GetProcAddress(kernel, "GetConsoleWindow");
450db522d3aSSimon L. B. Nielsen 	if (cryptui && !OPENSSL_isservice())
451db522d3aSSimon L. B. Nielsen 		ctx->client_cert_select = cert_select_dialog;
452db522d3aSSimon L. B. Nielsen 	}
453db522d3aSSimon L. B. Nielsen #endif
454db522d3aSSimon L. B. Nielsen 
455db522d3aSSimon L. B. Nielsen 
456db522d3aSSimon L. B. Nielsen 	return 1;
457db522d3aSSimon L. B. Nielsen 
458db522d3aSSimon L. B. Nielsen 	memerr:
459db522d3aSSimon L. B. Nielsen 	CAPIerr(CAPI_F_CAPI_INIT, ERR_R_MALLOC_FAILURE);
460db522d3aSSimon L. B. Nielsen 	return 0;
461db522d3aSSimon L. B. Nielsen 
462db522d3aSSimon L. B. Nielsen 	return 1;
463db522d3aSSimon L. B. Nielsen 	}
464db522d3aSSimon L. B. Nielsen 
465db522d3aSSimon L. B. Nielsen static int capi_destroy(ENGINE *e)
466db522d3aSSimon L. B. Nielsen 	{
467db522d3aSSimon L. B. Nielsen 	ERR_unload_CAPI_strings();
468db522d3aSSimon L. B. Nielsen 	return 1;
469db522d3aSSimon L. B. Nielsen 	}
470db522d3aSSimon L. B. Nielsen 
471db522d3aSSimon L. B. Nielsen static int capi_finish(ENGINE *e)
472db522d3aSSimon L. B. Nielsen 	{
473db522d3aSSimon L. B. Nielsen 	CAPI_CTX *ctx;
474db522d3aSSimon L. B. Nielsen 	ctx = ENGINE_get_ex_data(e, capi_idx);
475db522d3aSSimon L. B. Nielsen 	capi_ctx_free(ctx);
476db522d3aSSimon L. B. Nielsen 	ENGINE_set_ex_data(e, capi_idx, NULL);
477db522d3aSSimon L. B. Nielsen 	return 1;
478db522d3aSSimon L. B. Nielsen 	}
479db522d3aSSimon L. B. Nielsen 
480db522d3aSSimon L. B. Nielsen 
481db522d3aSSimon L. B. Nielsen /* CryptoAPI key application data. This contains
482db522d3aSSimon L. B. Nielsen  * a handle to the private key container (for sign operations)
483db522d3aSSimon L. B. Nielsen  * and a handle to the key (for decrypt operations).
484db522d3aSSimon L. B. Nielsen  */
485db522d3aSSimon L. B. Nielsen 
486db522d3aSSimon L. B. Nielsen struct CAPI_KEY_st
487db522d3aSSimon L. B. Nielsen 	{
488db522d3aSSimon L. B. Nielsen 	/* Associated certificate context (if any) */
489db522d3aSSimon L. B. Nielsen 	PCCERT_CONTEXT pcert;
490db522d3aSSimon L. B. Nielsen 	HCRYPTPROV hprov;
491db522d3aSSimon L. B. Nielsen 	HCRYPTKEY key;
492db522d3aSSimon L. B. Nielsen 	DWORD keyspec;
493db522d3aSSimon L. B. Nielsen 	};
494db522d3aSSimon L. B. Nielsen 
495db522d3aSSimon L. B. Nielsen static int bind_capi(ENGINE *e)
496db522d3aSSimon L. B. Nielsen 	{
497db522d3aSSimon L. B. Nielsen 	if (!ENGINE_set_id(e, engine_capi_id)
498db522d3aSSimon L. B. Nielsen 		|| !ENGINE_set_name(e, engine_capi_name)
499db522d3aSSimon L. B. Nielsen 		|| !ENGINE_set_init_function(e, capi_init)
500db522d3aSSimon L. B. Nielsen 		|| !ENGINE_set_finish_function(e, capi_finish)
501db522d3aSSimon L. B. Nielsen 		|| !ENGINE_set_destroy_function(e, capi_destroy)
502db522d3aSSimon L. B. Nielsen 		|| !ENGINE_set_RSA(e, &capi_rsa_method)
503db522d3aSSimon L. B. Nielsen 		|| !ENGINE_set_DSA(e, &capi_dsa_method)
504db522d3aSSimon L. B. Nielsen 		|| !ENGINE_set_load_privkey_function(e, capi_load_privkey)
505db522d3aSSimon L. B. Nielsen 		|| !ENGINE_set_load_ssl_client_cert_function(e,
506db522d3aSSimon L. B. Nielsen 						capi_load_ssl_client_cert)
507db522d3aSSimon L. B. Nielsen 		|| !ENGINE_set_cmd_defns(e, capi_cmd_defns)
508db522d3aSSimon L. B. Nielsen 		|| !ENGINE_set_ctrl_function(e, capi_ctrl))
509db522d3aSSimon L. B. Nielsen 			return 0;
510db522d3aSSimon L. B. Nielsen 	ERR_load_CAPI_strings();
511db522d3aSSimon L. B. Nielsen 
512db522d3aSSimon L. B. Nielsen 	return 1;
513db522d3aSSimon L. B. Nielsen 
514db522d3aSSimon L. B. Nielsen 	}
515db522d3aSSimon L. B. Nielsen 
516db522d3aSSimon L. B. Nielsen #ifndef OPENSSL_NO_DYNAMIC_ENGINE
517db522d3aSSimon L. B. Nielsen static int bind_helper(ENGINE *e, const char *id)
518db522d3aSSimon L. B. Nielsen 	{
519db522d3aSSimon L. B. Nielsen 	if(id && (strcmp(id, engine_capi_id) != 0))
520db522d3aSSimon L. B. Nielsen 		return 0;
521db522d3aSSimon L. B. Nielsen 	if(!bind_capi(e))
522db522d3aSSimon L. B. Nielsen 		return 0;
523db522d3aSSimon L. B. Nielsen 	return 1;
524db522d3aSSimon L. B. Nielsen 	}
525db522d3aSSimon L. B. Nielsen IMPLEMENT_DYNAMIC_CHECK_FN()
526db522d3aSSimon L. B. Nielsen IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
527db522d3aSSimon L. B. Nielsen #else
528db522d3aSSimon L. B. Nielsen static ENGINE *engine_capi(void)
529db522d3aSSimon L. B. Nielsen 	{
530db522d3aSSimon L. B. Nielsen 	ENGINE *ret = ENGINE_new();
531db522d3aSSimon L. B. Nielsen 	if(!ret)
532db522d3aSSimon L. B. Nielsen 		return NULL;
533db522d3aSSimon L. B. Nielsen 	if(!bind_capi(ret))
534db522d3aSSimon L. B. Nielsen 		{
535db522d3aSSimon L. B. Nielsen 		ENGINE_free(ret);
536db522d3aSSimon L. B. Nielsen 		return NULL;
537db522d3aSSimon L. B. Nielsen 		}
538db522d3aSSimon L. B. Nielsen 	return ret;
539db522d3aSSimon L. B. Nielsen 	}
540db522d3aSSimon L. B. Nielsen 
541db522d3aSSimon L. B. Nielsen void ENGINE_load_capi(void)
542db522d3aSSimon L. B. Nielsen 	{
543db522d3aSSimon L. B. Nielsen 	/* Copied from eng_[openssl|dyn].c */
544db522d3aSSimon L. B. Nielsen 	ENGINE *toadd = engine_capi();
545db522d3aSSimon L. B. Nielsen 	if(!toadd) return;
546db522d3aSSimon L. B. Nielsen 	ENGINE_add(toadd);
547db522d3aSSimon L. B. Nielsen 	ENGINE_free(toadd);
548db522d3aSSimon L. B. Nielsen 	ERR_clear_error();
549db522d3aSSimon L. B. Nielsen 	}
550db522d3aSSimon L. B. Nielsen #endif
551db522d3aSSimon L. B. Nielsen 
552db522d3aSSimon L. B. Nielsen 
553db522d3aSSimon L. B. Nielsen static int lend_tobn(BIGNUM *bn, unsigned char *bin, int binlen)
554db522d3aSSimon L. B. Nielsen 	{
555db522d3aSSimon L. B. Nielsen 	int i;
556db522d3aSSimon L. B. Nielsen 	/* Reverse buffer in place: since this is a keyblob structure
557db522d3aSSimon L. B. Nielsen 	 * that will be freed up after conversion anyway it doesn't
558db522d3aSSimon L. B. Nielsen 	 * matter if we change it.
559db522d3aSSimon L. B. Nielsen 	 */
560db522d3aSSimon L. B. Nielsen 	for(i = 0; i < binlen / 2; i++)
561db522d3aSSimon L. B. Nielsen 		{
562db522d3aSSimon L. B. Nielsen 		unsigned char c;
563db522d3aSSimon L. B. Nielsen 		c = bin[i];
564db522d3aSSimon L. B. Nielsen 		bin[i] = bin[binlen - i - 1];
565db522d3aSSimon L. B. Nielsen 		bin[binlen - i - 1] = c;
566db522d3aSSimon L. B. Nielsen 		}
567db522d3aSSimon L. B. Nielsen 
568db522d3aSSimon L. B. Nielsen 	if (!BN_bin2bn(bin, binlen, bn))
569db522d3aSSimon L. B. Nielsen 		return 0;
570db522d3aSSimon L. B. Nielsen 	return 1;
571db522d3aSSimon L. B. Nielsen 	}
572db522d3aSSimon L. B. Nielsen 
573db522d3aSSimon L. B. Nielsen /* Given a CAPI_KEY get an EVP_PKEY structure */
574db522d3aSSimon L. B. Nielsen 
575db522d3aSSimon L. B. Nielsen static EVP_PKEY *capi_get_pkey(ENGINE *eng, CAPI_KEY *key)
576db522d3aSSimon L. B. Nielsen 	{
577db522d3aSSimon L. B. Nielsen 	unsigned char *pubkey = NULL;
578db522d3aSSimon L. B. Nielsen 	DWORD len;
579db522d3aSSimon L. B. Nielsen 	BLOBHEADER *bh;
580db522d3aSSimon L. B. Nielsen 	RSA *rkey = NULL;
581db522d3aSSimon L. B. Nielsen 	DSA *dkey = NULL;
582db522d3aSSimon L. B. Nielsen 	EVP_PKEY *ret = NULL;
583db522d3aSSimon L. B. Nielsen 	if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, NULL, &len))
584db522d3aSSimon L. B. Nielsen 		{
585db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_LENGTH_ERROR);
586db522d3aSSimon L. B. Nielsen 		capi_addlasterror();
587db522d3aSSimon L. B. Nielsen 		return NULL;
588db522d3aSSimon L. B. Nielsen 		}
589db522d3aSSimon L. B. Nielsen 
590db522d3aSSimon L. B. Nielsen 	pubkey = OPENSSL_malloc(len);
591db522d3aSSimon L. B. Nielsen 
592db522d3aSSimon L. B. Nielsen 	if (!pubkey)
593db522d3aSSimon L. B. Nielsen 		goto memerr;
594db522d3aSSimon L. B. Nielsen 
595db522d3aSSimon L. B. Nielsen 	if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, pubkey, &len))
596db522d3aSSimon L. B. Nielsen 		{
597db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_ERROR);
598db522d3aSSimon L. B. Nielsen 		capi_addlasterror();
599db522d3aSSimon L. B. Nielsen 		goto err;
600db522d3aSSimon L. B. Nielsen 		}
601db522d3aSSimon L. B. Nielsen 
602db522d3aSSimon L. B. Nielsen 	bh = (BLOBHEADER *)pubkey;
603db522d3aSSimon L. B. Nielsen 	if (bh->bType != PUBLICKEYBLOB)
604db522d3aSSimon L. B. Nielsen 		{
605db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_PUBLIC_KEY_BLOB);
606db522d3aSSimon L. B. Nielsen 		goto err;
607db522d3aSSimon L. B. Nielsen 		}
608db522d3aSSimon L. B. Nielsen 	if (bh->aiKeyAlg == CALG_RSA_SIGN || bh->aiKeyAlg == CALG_RSA_KEYX)
609db522d3aSSimon L. B. Nielsen 		{
610db522d3aSSimon L. B. Nielsen 		RSAPUBKEY *rp;
611db522d3aSSimon L. B. Nielsen 		DWORD rsa_modlen;
612db522d3aSSimon L. B. Nielsen 		unsigned char *rsa_modulus;
613db522d3aSSimon L. B. Nielsen 		rp = (RSAPUBKEY *)(bh + 1);
614db522d3aSSimon L. B. Nielsen 		if (rp->magic != 0x31415352)
615db522d3aSSimon L. B. Nielsen 			{
616db522d3aSSimon L. B. Nielsen 			char magstr[10];
617db522d3aSSimon L. B. Nielsen 			BIO_snprintf(magstr, 10, "%lx", rp->magic);
618db522d3aSSimon L. B. Nielsen 			CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_RSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER);
619db522d3aSSimon L. B. Nielsen 			ERR_add_error_data(2, "magic=0x", magstr);
620db522d3aSSimon L. B. Nielsen 			goto err;
621db522d3aSSimon L. B. Nielsen 			}
622db522d3aSSimon L. B. Nielsen 		rsa_modulus = (unsigned char *)(rp + 1);
623db522d3aSSimon L. B. Nielsen 		rkey = RSA_new_method(eng);
624db522d3aSSimon L. B. Nielsen 		if (!rkey)
625db522d3aSSimon L. B. Nielsen 			goto memerr;
626db522d3aSSimon L. B. Nielsen 
627db522d3aSSimon L. B. Nielsen 		rkey->e = BN_new();
628db522d3aSSimon L. B. Nielsen 		rkey->n = BN_new();
629db522d3aSSimon L. B. Nielsen 
630db522d3aSSimon L. B. Nielsen 		if (!rkey->e || !rkey->n)
631db522d3aSSimon L. B. Nielsen 			goto memerr;
632db522d3aSSimon L. B. Nielsen 
633db522d3aSSimon L. B. Nielsen 		if (!BN_set_word(rkey->e, rp->pubexp))
634db522d3aSSimon L. B. Nielsen 			goto memerr;
635db522d3aSSimon L. B. Nielsen 
636db522d3aSSimon L. B. Nielsen 		rsa_modlen = rp->bitlen / 8;
637db522d3aSSimon L. B. Nielsen 		if (!lend_tobn(rkey->n, rsa_modulus, rsa_modlen))
638db522d3aSSimon L. B. Nielsen 			goto memerr;
639db522d3aSSimon L. B. Nielsen 
640db522d3aSSimon L. B. Nielsen 		RSA_set_ex_data(rkey, rsa_capi_idx, key);
641db522d3aSSimon L. B. Nielsen 
642db522d3aSSimon L. B. Nielsen 		if (!(ret = EVP_PKEY_new()))
643db522d3aSSimon L. B. Nielsen 			goto memerr;
644db522d3aSSimon L. B. Nielsen 
645db522d3aSSimon L. B. Nielsen 		EVP_PKEY_assign_RSA(ret, rkey);
646db522d3aSSimon L. B. Nielsen 		rkey = NULL;
647db522d3aSSimon L. B. Nielsen 
648db522d3aSSimon L. B. Nielsen 		}
649db522d3aSSimon L. B. Nielsen 	else if (bh->aiKeyAlg == CALG_DSS_SIGN)
650db522d3aSSimon L. B. Nielsen 		{
651db522d3aSSimon L. B. Nielsen 		DSSPUBKEY *dp;
652db522d3aSSimon L. B. Nielsen 		DWORD dsa_plen;
653db522d3aSSimon L. B. Nielsen 		unsigned char *btmp;
654db522d3aSSimon L. B. Nielsen 		dp = (DSSPUBKEY *)(bh + 1);
655db522d3aSSimon L. B. Nielsen 		if (dp->magic != 0x31535344)
656db522d3aSSimon L. B. Nielsen 			{
657db522d3aSSimon L. B. Nielsen 			char magstr[10];
658db522d3aSSimon L. B. Nielsen 			BIO_snprintf(magstr, 10, "%lx", dp->magic);
659db522d3aSSimon L. B. Nielsen 			CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_DSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER);
660db522d3aSSimon L. B. Nielsen 			ERR_add_error_data(2, "magic=0x", magstr);
661db522d3aSSimon L. B. Nielsen 			goto err;
662db522d3aSSimon L. B. Nielsen 			}
663db522d3aSSimon L. B. Nielsen 		dsa_plen = dp->bitlen / 8;
664db522d3aSSimon L. B. Nielsen 		btmp = (unsigned char *)(dp + 1);
665db522d3aSSimon L. B. Nielsen 		dkey = DSA_new_method(eng);
666db522d3aSSimon L. B. Nielsen 		if (!dkey)
667db522d3aSSimon L. B. Nielsen 			goto memerr;
668db522d3aSSimon L. B. Nielsen 		dkey->p = BN_new();
669db522d3aSSimon L. B. Nielsen 		dkey->q = BN_new();
670db522d3aSSimon L. B. Nielsen 		dkey->g = BN_new();
671db522d3aSSimon L. B. Nielsen 		dkey->pub_key = BN_new();
672db522d3aSSimon L. B. Nielsen 		if (!dkey->p || !dkey->q || !dkey->g || !dkey->pub_key)
673db522d3aSSimon L. B. Nielsen 			goto memerr;
674db522d3aSSimon L. B. Nielsen 		if (!lend_tobn(dkey->p, btmp, dsa_plen))
675db522d3aSSimon L. B. Nielsen 			goto memerr;
676db522d3aSSimon L. B. Nielsen 		btmp += dsa_plen;
677db522d3aSSimon L. B. Nielsen 		if (!lend_tobn(dkey->q, btmp, 20))
678db522d3aSSimon L. B. Nielsen 			goto memerr;
679db522d3aSSimon L. B. Nielsen 		btmp += 20;
680db522d3aSSimon L. B. Nielsen 		if (!lend_tobn(dkey->g, btmp, dsa_plen))
681db522d3aSSimon L. B. Nielsen 			goto memerr;
682db522d3aSSimon L. B. Nielsen 		btmp += dsa_plen;
683db522d3aSSimon L. B. Nielsen 		if (!lend_tobn(dkey->pub_key, btmp, dsa_plen))
684db522d3aSSimon L. B. Nielsen 			goto memerr;
685db522d3aSSimon L. B. Nielsen 		btmp += dsa_plen;
686db522d3aSSimon L. B. Nielsen 
687db522d3aSSimon L. B. Nielsen 		DSA_set_ex_data(dkey, dsa_capi_idx, key);
688db522d3aSSimon L. B. Nielsen 
689db522d3aSSimon L. B. Nielsen 		if (!(ret = EVP_PKEY_new()))
690db522d3aSSimon L. B. Nielsen 			goto memerr;
691db522d3aSSimon L. B. Nielsen 
692db522d3aSSimon L. B. Nielsen 		EVP_PKEY_assign_DSA(ret, dkey);
693db522d3aSSimon L. B. Nielsen 		dkey = NULL;
694db522d3aSSimon L. B. Nielsen 		}
695db522d3aSSimon L. B. Nielsen 	else
696db522d3aSSimon L. B. Nielsen 		{
697db522d3aSSimon L. B. Nielsen 		char algstr[10];
698db522d3aSSimon L. B. Nielsen 		BIO_snprintf(algstr, 10, "%lx", bh->aiKeyAlg);
699db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_UNSUPPORTED_PUBLIC_KEY_ALGORITHM);
700db522d3aSSimon L. B. Nielsen 		ERR_add_error_data(2, "aiKeyAlg=0x", algstr);
701db522d3aSSimon L. B. Nielsen 		goto err;
702db522d3aSSimon L. B. Nielsen 		}
703db522d3aSSimon L. B. Nielsen 
704db522d3aSSimon L. B. Nielsen 
705db522d3aSSimon L. B. Nielsen 	err:
706db522d3aSSimon L. B. Nielsen 	if (pubkey)
707db522d3aSSimon L. B. Nielsen 		OPENSSL_free(pubkey);
708db522d3aSSimon L. B. Nielsen 	if (!ret)
709db522d3aSSimon L. B. Nielsen 		{
710db522d3aSSimon L. B. Nielsen 		if (rkey)
711db522d3aSSimon L. B. Nielsen 			RSA_free(rkey);
712db522d3aSSimon L. B. Nielsen 		if (dkey)
713db522d3aSSimon L. B. Nielsen 			DSA_free(dkey);
714db522d3aSSimon L. B. Nielsen 		}
715db522d3aSSimon L. B. Nielsen 
716db522d3aSSimon L. B. Nielsen 	return ret;
717db522d3aSSimon L. B. Nielsen 
718db522d3aSSimon L. B. Nielsen memerr:
719db522d3aSSimon L. B. Nielsen 	CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_MALLOC_FAILURE);
720db522d3aSSimon L. B. Nielsen 	goto err;
721db522d3aSSimon L. B. Nielsen 
722db522d3aSSimon L. B. Nielsen 	}
723db522d3aSSimon L. B. Nielsen 
724db522d3aSSimon L. B. Nielsen static EVP_PKEY *capi_load_privkey(ENGINE *eng, const char *key_id,
725db522d3aSSimon L. B. Nielsen 	UI_METHOD *ui_method, void *callback_data)
726db522d3aSSimon L. B. Nielsen 	{
727db522d3aSSimon L. B. Nielsen 	CAPI_CTX *ctx;
728db522d3aSSimon L. B. Nielsen 	CAPI_KEY *key;
729db522d3aSSimon L. B. Nielsen 	EVP_PKEY *ret;
730db522d3aSSimon L. B. Nielsen 	ctx = ENGINE_get_ex_data(eng, capi_idx);
731db522d3aSSimon L. B. Nielsen 
732db522d3aSSimon L. B. Nielsen 	if (!ctx)
733db522d3aSSimon L. B. Nielsen 		{
734db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_LOAD_PRIVKEY, CAPI_R_CANT_FIND_CAPI_CONTEXT);
735db522d3aSSimon L. B. Nielsen 		return NULL;
736db522d3aSSimon L. B. Nielsen 		}
737db522d3aSSimon L. B. Nielsen 
738db522d3aSSimon L. B. Nielsen 	key = capi_find_key(ctx, key_id);
739db522d3aSSimon L. B. Nielsen 
740db522d3aSSimon L. B. Nielsen 	if (!key)
741db522d3aSSimon L. B. Nielsen 		return NULL;
742db522d3aSSimon L. B. Nielsen 
743db522d3aSSimon L. B. Nielsen 	ret = capi_get_pkey(eng, key);
744db522d3aSSimon L. B. Nielsen 
745db522d3aSSimon L. B. Nielsen 	if (!ret)
746db522d3aSSimon L. B. Nielsen 		capi_free_key(key);
747db522d3aSSimon L. B. Nielsen 	return ret;
748db522d3aSSimon L. B. Nielsen 
749db522d3aSSimon L. B. Nielsen 	}
750db522d3aSSimon L. B. Nielsen 
751db522d3aSSimon L. B. Nielsen /* CryptoAPI RSA operations */
752db522d3aSSimon L. B. Nielsen 
753db522d3aSSimon L. B. Nielsen int capi_rsa_priv_enc(int flen, const unsigned char *from,
754db522d3aSSimon L. B. Nielsen                 unsigned char *to, RSA *rsa, int padding)
755db522d3aSSimon L. B. Nielsen 	{
756db522d3aSSimon L. B. Nielsen 	CAPIerr(CAPI_F_CAPI_RSA_PRIV_ENC, CAPI_R_FUNCTION_NOT_SUPPORTED);
757db522d3aSSimon L. B. Nielsen 	return -1;
758db522d3aSSimon L. B. Nielsen 	}
759db522d3aSSimon L. B. Nielsen 
760db522d3aSSimon L. B. Nielsen int capi_rsa_sign(int dtype, const unsigned char *m, unsigned int m_len,
761db522d3aSSimon L. B. Nielsen              unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
762db522d3aSSimon L. B. Nielsen 	{
763db522d3aSSimon L. B. Nielsen 	ALG_ID alg;
764db522d3aSSimon L. B. Nielsen 	HCRYPTHASH hash;
765db522d3aSSimon L. B. Nielsen 	DWORD slen;
766db522d3aSSimon L. B. Nielsen 	unsigned int i;
767db522d3aSSimon L. B. Nielsen 	int ret = -1;
768db522d3aSSimon L. B. Nielsen 	CAPI_KEY *capi_key;
769db522d3aSSimon L. B. Nielsen 	CAPI_CTX *ctx;
770db522d3aSSimon L. B. Nielsen 
771db522d3aSSimon L. B. Nielsen 	ctx = ENGINE_get_ex_data(rsa->engine, capi_idx);
772db522d3aSSimon L. B. Nielsen 
773db522d3aSSimon L. B. Nielsen 	CAPI_trace(ctx, "Called CAPI_rsa_sign()\n");
774db522d3aSSimon L. B. Nielsen 
775db522d3aSSimon L. B. Nielsen 	capi_key = RSA_get_ex_data(rsa, rsa_capi_idx);
776db522d3aSSimon L. B. Nielsen 	if (!capi_key)
777db522d3aSSimon L. B. Nielsen 		{
778db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_GET_KEY);
779db522d3aSSimon L. B. Nielsen 		return -1;
780db522d3aSSimon L. B. Nielsen 		}
781db522d3aSSimon L. B. Nielsen /* Convert the signature type to a CryptoAPI algorithm ID */
782db522d3aSSimon L. B. Nielsen 	switch(dtype)
783db522d3aSSimon L. B. Nielsen 		{
784db522d3aSSimon L. B. Nielsen 	case NID_sha1:
785db522d3aSSimon L. B. Nielsen 		alg = CALG_SHA1;
786db522d3aSSimon L. B. Nielsen 		break;
787db522d3aSSimon L. B. Nielsen 
788db522d3aSSimon L. B. Nielsen 	case NID_md5:
789db522d3aSSimon L. B. Nielsen 		alg = CALG_MD5;
790db522d3aSSimon L. B. Nielsen 		break;
791db522d3aSSimon L. B. Nielsen 
792db522d3aSSimon L. B. Nielsen 	case NID_md5_sha1:
793db522d3aSSimon L. B. Nielsen 		alg = CALG_SSL3_SHAMD5;
794db522d3aSSimon L. B. Nielsen 		break;
795db522d3aSSimon L. B. Nielsen 	default:
796db522d3aSSimon L. B. Nielsen 		{
797db522d3aSSimon L. B. Nielsen 		char algstr[10];
798db522d3aSSimon L. B. Nielsen 		BIO_snprintf(algstr, 10, "%lx", dtype);
799db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_UNSUPPORTED_ALGORITHM_NID);
800db522d3aSSimon L. B. Nielsen 		ERR_add_error_data(2, "NID=0x", algstr);
801db522d3aSSimon L. B. Nielsen 		return -1;
802db522d3aSSimon L. B. Nielsen 		}
803db522d3aSSimon L. B. Nielsen 	}
804db522d3aSSimon L. B. Nielsen 
805db522d3aSSimon L. B. Nielsen 
806db522d3aSSimon L. B. Nielsen 
807db522d3aSSimon L. B. Nielsen /* Create the hash object */
808db522d3aSSimon L. B. Nielsen 	if(!CryptCreateHash(capi_key->hprov, alg, 0, 0, &hash))
809db522d3aSSimon L. B. Nielsen 		{
810db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT);
811db522d3aSSimon L. B. Nielsen 		capi_addlasterror();
812db522d3aSSimon L. B. Nielsen 		return -1;
813db522d3aSSimon L. B. Nielsen 		}
814db522d3aSSimon L. B. Nielsen /* Set the hash value to the value passed */
815db522d3aSSimon L. B. Nielsen 
816db522d3aSSimon L. B. Nielsen 	if(!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)m, 0))
817db522d3aSSimon L. B. Nielsen 		{
818db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_SET_HASH_VALUE);
819db522d3aSSimon L. B. Nielsen 		capi_addlasterror();
820db522d3aSSimon L. B. Nielsen 		goto err;
821db522d3aSSimon L. B. Nielsen 		}
822db522d3aSSimon L. B. Nielsen 
823db522d3aSSimon L. B. Nielsen 
824db522d3aSSimon L. B. Nielsen /* Finally sign it */
825db522d3aSSimon L. B. Nielsen 	slen = RSA_size(rsa);
826db522d3aSSimon L. B. Nielsen 	if(!CryptSignHash(hash, capi_key->keyspec, NULL, 0, sigret, &slen))
827db522d3aSSimon L. B. Nielsen 		{
828db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_ERROR_SIGNING_HASH);
829db522d3aSSimon L. B. Nielsen 		capi_addlasterror();
830db522d3aSSimon L. B. Nielsen 		goto err;
831db522d3aSSimon L. B. Nielsen 		}
832db522d3aSSimon L. B. Nielsen 	else
833db522d3aSSimon L. B. Nielsen 		{
834db522d3aSSimon L. B. Nielsen 		ret = 1;
835db522d3aSSimon L. B. Nielsen 		/* Inplace byte reversal of signature */
836db522d3aSSimon L. B. Nielsen 		for(i = 0; i < slen / 2; i++)
837db522d3aSSimon L. B. Nielsen 			{
838db522d3aSSimon L. B. Nielsen 			unsigned char c;
839db522d3aSSimon L. B. Nielsen 			c = sigret[i];
840db522d3aSSimon L. B. Nielsen 			sigret[i] = sigret[slen - i - 1];
841db522d3aSSimon L. B. Nielsen 			sigret[slen - i - 1] = c;
842db522d3aSSimon L. B. Nielsen 			}
843db522d3aSSimon L. B. Nielsen 		*siglen = slen;
844db522d3aSSimon L. B. Nielsen 		}
845db522d3aSSimon L. B. Nielsen 
846db522d3aSSimon L. B. Nielsen 	/* Now cleanup */
847db522d3aSSimon L. B. Nielsen 
848db522d3aSSimon L. B. Nielsen err:
849db522d3aSSimon L. B. Nielsen 	CryptDestroyHash(hash);
850db522d3aSSimon L. B. Nielsen 
851db522d3aSSimon L. B. Nielsen 	return ret;
852db522d3aSSimon L. B. Nielsen 	}
853db522d3aSSimon L. B. Nielsen 
854db522d3aSSimon L. B. Nielsen int capi_rsa_priv_dec(int flen, const unsigned char *from,
855db522d3aSSimon L. B. Nielsen                 unsigned char *to, RSA *rsa, int padding)
856db522d3aSSimon L. B. Nielsen 	{
857db522d3aSSimon L. B. Nielsen 	int i;
858db522d3aSSimon L. B. Nielsen 	unsigned char *tmpbuf;
859db522d3aSSimon L. B. Nielsen 	CAPI_KEY *capi_key;
860db522d3aSSimon L. B. Nielsen 	CAPI_CTX *ctx;
861db522d3aSSimon L. B. Nielsen 	ctx = ENGINE_get_ex_data(rsa->engine, capi_idx);
862db522d3aSSimon L. B. Nielsen 
863db522d3aSSimon L. B. Nielsen 	CAPI_trace(ctx, "Called capi_rsa_priv_dec()\n");
864db522d3aSSimon L. B. Nielsen 
865db522d3aSSimon L. B. Nielsen 
866db522d3aSSimon L. B. Nielsen 	capi_key = RSA_get_ex_data(rsa, rsa_capi_idx);
867db522d3aSSimon L. B. Nielsen 	if (!capi_key)
868db522d3aSSimon L. B. Nielsen 		{
869db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_CANT_GET_KEY);
870db522d3aSSimon L. B. Nielsen 		return -1;
871db522d3aSSimon L. B. Nielsen 		}
872db522d3aSSimon L. B. Nielsen 
873db522d3aSSimon L. B. Nielsen 	if(padding != RSA_PKCS1_PADDING)
874db522d3aSSimon L. B. Nielsen 		{
875db522d3aSSimon L. B. Nielsen 		char errstr[10];
876db522d3aSSimon L. B. Nielsen 		BIO_snprintf(errstr, 10, "%d", padding);
877db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_UNSUPPORTED_PADDING);
878db522d3aSSimon L. B. Nielsen 		ERR_add_error_data(2, "padding=", errstr);
879db522d3aSSimon L. B. Nielsen 		return -1;
880db522d3aSSimon L. B. Nielsen 		}
881db522d3aSSimon L. B. Nielsen 
882db522d3aSSimon L. B. Nielsen 	/* Create temp reverse order version of input */
883db522d3aSSimon L. B. Nielsen 	if(!(tmpbuf = OPENSSL_malloc(flen)) )
884db522d3aSSimon L. B. Nielsen 		{
885db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, ERR_R_MALLOC_FAILURE);
886db522d3aSSimon L. B. Nielsen 		return -1;
887db522d3aSSimon L. B. Nielsen 		}
888db522d3aSSimon L. B. Nielsen 	for(i = 0; i < flen; i++)
889db522d3aSSimon L. B. Nielsen 		tmpbuf[flen - i - 1] = from[i];
890db522d3aSSimon L. B. Nielsen 
891db522d3aSSimon L. B. Nielsen 	/* Finally decrypt it */
892db522d3aSSimon L. B. Nielsen 	if(!CryptDecrypt(capi_key->key, 0, TRUE, 0, tmpbuf, &flen))
893db522d3aSSimon L. B. Nielsen 		{
894db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_DECRYPT_ERROR);
895db522d3aSSimon L. B. Nielsen 		capi_addlasterror();
896db522d3aSSimon L. B. Nielsen 		OPENSSL_free(tmpbuf);
897db522d3aSSimon L. B. Nielsen 		return -1;
898db522d3aSSimon L. B. Nielsen 		}
899db522d3aSSimon L. B. Nielsen 	else memcpy(to, tmpbuf, flen);
900db522d3aSSimon L. B. Nielsen 
901db522d3aSSimon L. B. Nielsen 	OPENSSL_free(tmpbuf);
902db522d3aSSimon L. B. Nielsen 
903db522d3aSSimon L. B. Nielsen 	return flen;
904db522d3aSSimon L. B. Nielsen 	}
905db522d3aSSimon L. B. Nielsen 
906db522d3aSSimon L. B. Nielsen static int capi_rsa_free(RSA *rsa)
907db522d3aSSimon L. B. Nielsen 	{
908db522d3aSSimon L. B. Nielsen 	CAPI_KEY *capi_key;
909db522d3aSSimon L. B. Nielsen 	capi_key = RSA_get_ex_data(rsa, rsa_capi_idx);
910db522d3aSSimon L. B. Nielsen 	capi_free_key(capi_key);
911db522d3aSSimon L. B. Nielsen 	RSA_set_ex_data(rsa, rsa_capi_idx, 0);
912db522d3aSSimon L. B. Nielsen 	return 1;
913db522d3aSSimon L. B. Nielsen 	}
914db522d3aSSimon L. B. Nielsen 
915db522d3aSSimon L. B. Nielsen /* CryptoAPI DSA operations */
916db522d3aSSimon L. B. Nielsen 
917db522d3aSSimon L. B. Nielsen static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen,
918db522d3aSSimon L. B. Nielsen 								DSA *dsa)
919db522d3aSSimon L. B. Nielsen 	{
920db522d3aSSimon L. B. Nielsen 	HCRYPTHASH hash;
921db522d3aSSimon L. B. Nielsen 	DWORD slen;
922db522d3aSSimon L. B. Nielsen 	DSA_SIG *ret = NULL;
923db522d3aSSimon L. B. Nielsen 	CAPI_KEY *capi_key;
924db522d3aSSimon L. B. Nielsen 	CAPI_CTX *ctx;
925db522d3aSSimon L. B. Nielsen 	unsigned char csigbuf[40];
926db522d3aSSimon L. B. Nielsen 
927db522d3aSSimon L. B. Nielsen 	ctx = ENGINE_get_ex_data(dsa->engine, capi_idx);
928db522d3aSSimon L. B. Nielsen 
929db522d3aSSimon L. B. Nielsen 	CAPI_trace(ctx, "Called CAPI_dsa_do_sign()\n");
930db522d3aSSimon L. B. Nielsen 
931db522d3aSSimon L. B. Nielsen 	capi_key = DSA_get_ex_data(dsa, dsa_capi_idx);
932db522d3aSSimon L. B. Nielsen 
933db522d3aSSimon L. B. Nielsen 	if (!capi_key)
934db522d3aSSimon L. B. Nielsen 		{
935db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_GET_KEY);
936db522d3aSSimon L. B. Nielsen 		return NULL;
937db522d3aSSimon L. B. Nielsen 		}
938db522d3aSSimon L. B. Nielsen 
939db522d3aSSimon L. B. Nielsen 	if (dlen != 20)
940db522d3aSSimon L. B. Nielsen 		{
941db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_INVALID_DIGEST_LENGTH);
942db522d3aSSimon L. B. Nielsen 		return NULL;
943db522d3aSSimon L. B. Nielsen 		}
944db522d3aSSimon L. B. Nielsen 
945db522d3aSSimon L. B. Nielsen 	/* Create the hash object */
946db522d3aSSimon L. B. Nielsen 	if(!CryptCreateHash(capi_key->hprov, CALG_SHA1, 0, 0, &hash))
947db522d3aSSimon L. B. Nielsen 		{
948db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT);
949db522d3aSSimon L. B. Nielsen 		capi_addlasterror();
950db522d3aSSimon L. B. Nielsen 		return NULL;
951db522d3aSSimon L. B. Nielsen 		}
952db522d3aSSimon L. B. Nielsen 
953db522d3aSSimon L. B. Nielsen 	/* Set the hash value to the value passed */
954db522d3aSSimon L. B. Nielsen 	if(!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)digest, 0))
955db522d3aSSimon L. B. Nielsen 		{
956db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_SET_HASH_VALUE);
957db522d3aSSimon L. B. Nielsen 		capi_addlasterror();
958db522d3aSSimon L. B. Nielsen 		goto err;
959db522d3aSSimon L. B. Nielsen 		}
960db522d3aSSimon L. B. Nielsen 
961db522d3aSSimon L. B. Nielsen 
962db522d3aSSimon L. B. Nielsen 	/* Finally sign it */
963db522d3aSSimon L. B. Nielsen 	slen = sizeof(csigbuf);
964db522d3aSSimon L. B. Nielsen 	if(!CryptSignHash(hash, capi_key->keyspec, NULL, 0, csigbuf, &slen))
965db522d3aSSimon L. B. Nielsen 		{
966db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_ERROR_SIGNING_HASH);
967db522d3aSSimon L. B. Nielsen 		capi_addlasterror();
968db522d3aSSimon L. B. Nielsen 		goto err;
969db522d3aSSimon L. B. Nielsen 		}
970db522d3aSSimon L. B. Nielsen 	else
971db522d3aSSimon L. B. Nielsen 		{
972db522d3aSSimon L. B. Nielsen 		ret = DSA_SIG_new();
973db522d3aSSimon L. B. Nielsen 		if (!ret)
974db522d3aSSimon L. B. Nielsen 			goto err;
975db522d3aSSimon L. B. Nielsen 		ret->r = BN_new();
976db522d3aSSimon L. B. Nielsen 		ret->s = BN_new();
977db522d3aSSimon L. B. Nielsen 		if (!ret->r || !ret->s)
978db522d3aSSimon L. B. Nielsen 			goto err;
979db522d3aSSimon L. B. Nielsen 		if (!lend_tobn(ret->r, csigbuf, 20)
980db522d3aSSimon L. B. Nielsen 			|| !lend_tobn(ret->s, csigbuf + 20, 20))
981db522d3aSSimon L. B. Nielsen 			{
982db522d3aSSimon L. B. Nielsen 			DSA_SIG_free(ret);
983db522d3aSSimon L. B. Nielsen 			ret = NULL;
984db522d3aSSimon L. B. Nielsen 			goto err;
985db522d3aSSimon L. B. Nielsen 			}
986db522d3aSSimon L. B. Nielsen 		}
987db522d3aSSimon L. B. Nielsen 
988db522d3aSSimon L. B. Nielsen 	/* Now cleanup */
989db522d3aSSimon L. B. Nielsen 
990db522d3aSSimon L. B. Nielsen err:
991db522d3aSSimon L. B. Nielsen 	OPENSSL_cleanse(csigbuf, 40);
992db522d3aSSimon L. B. Nielsen 	CryptDestroyHash(hash);
993db522d3aSSimon L. B. Nielsen 	return ret;
994db522d3aSSimon L. B. Nielsen 	}
995db522d3aSSimon L. B. Nielsen 
996db522d3aSSimon L. B. Nielsen static int capi_dsa_free(DSA *dsa)
997db522d3aSSimon L. B. Nielsen 	{
998db522d3aSSimon L. B. Nielsen 	CAPI_KEY *capi_key;
999db522d3aSSimon L. B. Nielsen 	capi_key = DSA_get_ex_data(dsa, dsa_capi_idx);
1000db522d3aSSimon L. B. Nielsen 	capi_free_key(capi_key);
1001db522d3aSSimon L. B. Nielsen 	DSA_set_ex_data(dsa, dsa_capi_idx, 0);
1002db522d3aSSimon L. B. Nielsen 	return 1;
1003db522d3aSSimon L. B. Nielsen 	}
1004db522d3aSSimon L. B. Nielsen 
1005db522d3aSSimon L. B. Nielsen static void capi_vtrace(CAPI_CTX *ctx, int level, char *format, va_list argptr)
1006db522d3aSSimon L. B. Nielsen 	{
1007db522d3aSSimon L. B. Nielsen 	BIO *out;
1008db522d3aSSimon L. B. Nielsen 
1009db522d3aSSimon L. B. Nielsen 	if (!ctx || (ctx->debug_level < level) || (!ctx->debug_file))
1010db522d3aSSimon L. B. Nielsen 		return;
1011db522d3aSSimon L. B. Nielsen 	out = BIO_new_file(ctx->debug_file, "a+");
1012db522d3aSSimon L. B. Nielsen 	BIO_vprintf(out, format, argptr);
1013db522d3aSSimon L. B. Nielsen 	BIO_free(out);
1014db522d3aSSimon L. B. Nielsen 	}
1015db522d3aSSimon L. B. Nielsen 
1016db522d3aSSimon L. B. Nielsen static void CAPI_trace(CAPI_CTX *ctx, char *format, ...)
1017db522d3aSSimon L. B. Nielsen 	{
1018db522d3aSSimon L. B. Nielsen 	va_list args;
1019db522d3aSSimon L. B. Nielsen 	va_start(args, format);
1020db522d3aSSimon L. B. Nielsen 	capi_vtrace(ctx, CAPI_DBG_TRACE, format, args);
1021db522d3aSSimon L. B. Nielsen 	va_end(args);
1022db522d3aSSimon L. B. Nielsen 	}
1023db522d3aSSimon L. B. Nielsen 
1024db522d3aSSimon L. B. Nielsen static void capi_addlasterror(void)
1025db522d3aSSimon L. B. Nielsen 	{
1026db522d3aSSimon L. B. Nielsen 	capi_adderror(GetLastError());
1027db522d3aSSimon L. B. Nielsen 	}
1028db522d3aSSimon L. B. Nielsen 
1029db522d3aSSimon L. B. Nielsen static void capi_adderror(DWORD err)
1030db522d3aSSimon L. B. Nielsen 	{
1031db522d3aSSimon L. B. Nielsen 	char errstr[10];
1032db522d3aSSimon L. B. Nielsen 	BIO_snprintf(errstr, 10, "%lX", err);
1033db522d3aSSimon L. B. Nielsen 	ERR_add_error_data(2, "Error code= 0x", errstr);
1034db522d3aSSimon L. B. Nielsen 	}
1035db522d3aSSimon L. B. Nielsen 
1036db522d3aSSimon L. B. Nielsen static char *wide_to_asc(LPWSTR wstr)
1037db522d3aSSimon L. B. Nielsen 	{
1038db522d3aSSimon L. B. Nielsen 	char *str;
1039db522d3aSSimon L. B. Nielsen 	if (!wstr)
1040db522d3aSSimon L. B. Nielsen 		return NULL;
1041db522d3aSSimon L. B. Nielsen 	str = OPENSSL_malloc(wcslen(wstr) + 1);
1042db522d3aSSimon L. B. Nielsen 	if (!str)
1043db522d3aSSimon L. B. Nielsen 		{
1044db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_WIDE_TO_ASC, ERR_R_MALLOC_FAILURE);
1045db522d3aSSimon L. B. Nielsen 		return NULL;
1046db522d3aSSimon L. B. Nielsen 		}
1047db522d3aSSimon L. B. Nielsen 	sprintf(str, "%S", wstr);
1048db522d3aSSimon L. B. Nielsen 	return str;
1049db522d3aSSimon L. B. Nielsen 	}
1050db522d3aSSimon L. B. Nielsen 
1051db522d3aSSimon L. B. Nielsen static int capi_get_provname(CAPI_CTX *ctx, LPSTR *pname, DWORD *ptype, DWORD idx)
1052db522d3aSSimon L. B. Nielsen 	{
1053db522d3aSSimon L. B. Nielsen 	LPSTR name;
1054db522d3aSSimon L. B. Nielsen 	DWORD len, err;
1055db522d3aSSimon L. B. Nielsen 	CAPI_trace(ctx, "capi_get_provname, index=%d\n", idx);
1056db522d3aSSimon L. B. Nielsen 	if (!CryptEnumProviders(idx, NULL, 0, ptype, NULL, &len))
1057db522d3aSSimon L. B. Nielsen 		{
1058db522d3aSSimon L. B. Nielsen 		err = GetLastError();
1059db522d3aSSimon L. B. Nielsen 		if (err == ERROR_NO_MORE_ITEMS)
1060db522d3aSSimon L. B. Nielsen 			return 2;
1061db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_GET_PROVNAME, CAPI_R_CRYPTENUMPROVIDERS_ERROR);
1062db522d3aSSimon L. B. Nielsen 		capi_adderror(err);
1063db522d3aSSimon L. B. Nielsen 		return 0;
1064db522d3aSSimon L. B. Nielsen 		}
1065db522d3aSSimon L. B. Nielsen 	name = OPENSSL_malloc(len);
1066db522d3aSSimon L. B. Nielsen 		if (!CryptEnumProviders(idx, NULL, 0, ptype, name, &len))
1067db522d3aSSimon L. B. Nielsen 		{
1068db522d3aSSimon L. B. Nielsen 		err = GetLastError();
1069db522d3aSSimon L. B. Nielsen 		if (err == ERROR_NO_MORE_ITEMS)
1070db522d3aSSimon L. B. Nielsen 			return 2;
1071db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_GET_PROVNAME, CAPI_R_CRYPTENUMPROVIDERS_ERROR);
1072db522d3aSSimon L. B. Nielsen 		capi_adderror(err);
1073db522d3aSSimon L. B. Nielsen 		return 0;
1074db522d3aSSimon L. B. Nielsen 		}
1075db522d3aSSimon L. B. Nielsen 	*pname = name;
1076db522d3aSSimon L. B. Nielsen 	CAPI_trace(ctx, "capi_get_provname, returned name=%s, type=%d\n", name, *ptype);
1077db522d3aSSimon L. B. Nielsen 
1078db522d3aSSimon L. B. Nielsen 	return 1;
1079db522d3aSSimon L. B. Nielsen 	}
1080db522d3aSSimon L. B. Nielsen 
1081db522d3aSSimon L. B. Nielsen static int capi_list_providers(CAPI_CTX *ctx, BIO *out)
1082db522d3aSSimon L. B. Nielsen 	{
1083db522d3aSSimon L. B. Nielsen 	DWORD idx, ptype;
1084db522d3aSSimon L. B. Nielsen 	int ret;
1085db522d3aSSimon L. B. Nielsen 	LPTSTR provname = NULL;
1086db522d3aSSimon L. B. Nielsen 	CAPI_trace(ctx, "capi_list_providers\n");
1087db522d3aSSimon L. B. Nielsen 	BIO_printf(out, "Available CSPs:\n");
1088db522d3aSSimon L. B. Nielsen 	for(idx = 0; ; idx++)
1089db522d3aSSimon L. B. Nielsen 		{
1090db522d3aSSimon L. B. Nielsen 		ret = capi_get_provname(ctx, &provname, &ptype, idx);
1091db522d3aSSimon L. B. Nielsen 		if (ret == 2)
1092db522d3aSSimon L. B. Nielsen 			break;
1093db522d3aSSimon L. B. Nielsen 		if (ret == 0)
1094db522d3aSSimon L. B. Nielsen 			break;
1095db522d3aSSimon L. B. Nielsen 		BIO_printf(out, "%d. %s, type %d\n", idx, provname, ptype);
1096db522d3aSSimon L. B. Nielsen 		OPENSSL_free(provname);
1097db522d3aSSimon L. B. Nielsen 		}
1098db522d3aSSimon L. B. Nielsen 	return 1;
1099db522d3aSSimon L. B. Nielsen 	}
1100db522d3aSSimon L. B. Nielsen 
1101db522d3aSSimon L. B. Nielsen static int capi_list_containers(CAPI_CTX *ctx, BIO *out)
1102db522d3aSSimon L. B. Nielsen 	{
1103db522d3aSSimon L. B. Nielsen 	int ret = 1;
1104db522d3aSSimon L. B. Nielsen 	HCRYPTPROV hprov;
1105db522d3aSSimon L. B. Nielsen 	DWORD err, idx, flags, buflen = 0, clen;
1106db522d3aSSimon L. B. Nielsen 	LPSTR cname;
1107db522d3aSSimon L. B. Nielsen 	CAPI_trace(ctx, "Listing containers CSP=%s, type = %d\n", ctx->cspname, ctx->csptype);
1108db522d3aSSimon L. B. Nielsen 	if (!CryptAcquireContext(&hprov, NULL, ctx->cspname, ctx->csptype, CRYPT_VERIFYCONTEXT))
1109db522d3aSSimon L. B. Nielsen 		{
1110db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_CRYPTACQUIRECONTEXT_ERROR);
1111db522d3aSSimon L. B. Nielsen 		capi_addlasterror();
1112db522d3aSSimon L. B. Nielsen 		return 0;
1113db522d3aSSimon L. B. Nielsen 		}
1114db522d3aSSimon L. B. Nielsen 	if (!CryptGetProvParam(hprov, PP_ENUMCONTAINERS, NULL, &buflen, CRYPT_FIRST))
1115db522d3aSSimon L. B. Nielsen 		{
1116db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_ENUMCONTAINERS_ERROR);
1117db522d3aSSimon L. B. Nielsen 		capi_addlasterror();
1118db522d3aSSimon L. B. Nielsen 		return 0;
1119db522d3aSSimon L. B. Nielsen 		}
1120db522d3aSSimon L. B. Nielsen 	CAPI_trace(ctx, "Got max container len %d\n", buflen);
1121db522d3aSSimon L. B. Nielsen 	if (buflen == 0)
1122db522d3aSSimon L. B. Nielsen 		buflen = 1024;
1123db522d3aSSimon L. B. Nielsen 	cname = OPENSSL_malloc(buflen);
1124db522d3aSSimon L. B. Nielsen 	if (!cname)
1125db522d3aSSimon L. B. Nielsen 		{
1126db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, ERR_R_MALLOC_FAILURE);
1127db522d3aSSimon L. B. Nielsen 		goto err;
1128db522d3aSSimon L. B. Nielsen 		}
1129db522d3aSSimon L. B. Nielsen 
1130db522d3aSSimon L. B. Nielsen 	for (idx = 0;;idx++)
1131db522d3aSSimon L. B. Nielsen 		{
1132db522d3aSSimon L. B. Nielsen 		clen = buflen;
1133db522d3aSSimon L. B. Nielsen 		cname[0] = 0;
1134db522d3aSSimon L. B. Nielsen 
1135db522d3aSSimon L. B. Nielsen 		if (idx == 0)
1136db522d3aSSimon L. B. Nielsen 			flags = CRYPT_FIRST;
1137db522d3aSSimon L. B. Nielsen 		else
1138db522d3aSSimon L. B. Nielsen 			flags = 0;
1139db522d3aSSimon L. B. Nielsen 		if(!CryptGetProvParam(hprov, PP_ENUMCONTAINERS, cname, &clen, flags))
1140db522d3aSSimon L. B. Nielsen 			{
1141db522d3aSSimon L. B. Nielsen 			err = GetLastError();
1142db522d3aSSimon L. B. Nielsen 			if (err == ERROR_NO_MORE_ITEMS)
1143db522d3aSSimon L. B. Nielsen 				goto done;
1144db522d3aSSimon L. B. Nielsen 			CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_ENUMCONTAINERS_ERROR);
1145db522d3aSSimon L. B. Nielsen 			capi_adderror(err);
1146db522d3aSSimon L. B. Nielsen 			goto err;
1147db522d3aSSimon L. B. Nielsen 			}
1148db522d3aSSimon L. B. Nielsen 		CAPI_trace(ctx, "Container name %s, len=%d, index=%d, flags=%d\n", cname, clen, idx, flags);
1149db522d3aSSimon L. B. Nielsen 		if (!cname[0] && (clen == buflen))
1150db522d3aSSimon L. B. Nielsen 			{
1151db522d3aSSimon L. B. Nielsen 			CAPI_trace(ctx, "Enumerate bug: using workaround\n");
1152db522d3aSSimon L. B. Nielsen 			goto done;
1153db522d3aSSimon L. B. Nielsen 			}
1154db522d3aSSimon L. B. Nielsen 		BIO_printf(out, "%d. %s\n", idx, cname);
1155db522d3aSSimon L. B. Nielsen 		}
1156db522d3aSSimon L. B. Nielsen 	err:
1157db522d3aSSimon L. B. Nielsen 
1158db522d3aSSimon L. B. Nielsen 	ret = 0;
1159db522d3aSSimon L. B. Nielsen 
1160db522d3aSSimon L. B. Nielsen 	done:
1161db522d3aSSimon L. B. Nielsen 	if (cname)
1162db522d3aSSimon L. B. Nielsen 		OPENSSL_free(cname);
1163db522d3aSSimon L. B. Nielsen 	CryptReleaseContext(hprov, 0);
1164db522d3aSSimon L. B. Nielsen 
1165db522d3aSSimon L. B. Nielsen 	return ret;
1166db522d3aSSimon L. B. Nielsen 	}
1167db522d3aSSimon L. B. Nielsen 
1168db522d3aSSimon L. B. Nielsen CRYPT_KEY_PROV_INFO *capi_get_prov_info(CAPI_CTX *ctx, PCCERT_CONTEXT cert)
1169db522d3aSSimon L. B. Nielsen 	{
1170db522d3aSSimon L. B. Nielsen 	DWORD len;
1171db522d3aSSimon L. B. Nielsen 	CRYPT_KEY_PROV_INFO *pinfo;
1172db522d3aSSimon L. B. Nielsen 
1173db522d3aSSimon L. B. Nielsen 	if(!CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &len))
1174db522d3aSSimon L. B. Nielsen 		return NULL;
1175db522d3aSSimon L. B. Nielsen 	pinfo = OPENSSL_malloc(len);
1176db522d3aSSimon L. B. Nielsen 	if (!pinfo)
1177db522d3aSSimon L. B. Nielsen 		{
1178db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_GET_PROV_INFO, ERR_R_MALLOC_FAILURE);
1179db522d3aSSimon L. B. Nielsen 		return NULL;
1180db522d3aSSimon L. B. Nielsen 		}
1181db522d3aSSimon L. B. Nielsen 	if(!CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, pinfo, &len))
1182db522d3aSSimon L. B. Nielsen 		{
1183db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_GET_PROV_INFO, CAPI_R_ERROR_GETTING_KEY_PROVIDER_INFO);
1184db522d3aSSimon L. B. Nielsen 		capi_addlasterror();
1185db522d3aSSimon L. B. Nielsen 		OPENSSL_free(pinfo);
1186db522d3aSSimon L. B. Nielsen 		return NULL;
1187db522d3aSSimon L. B. Nielsen 		}
1188db522d3aSSimon L. B. Nielsen 	return pinfo;
1189db522d3aSSimon L. B. Nielsen 	}
1190db522d3aSSimon L. B. Nielsen 
1191db522d3aSSimon L. B. Nielsen static void capi_dump_prov_info(CAPI_CTX *ctx, BIO *out, CRYPT_KEY_PROV_INFO *pinfo)
1192db522d3aSSimon L. B. Nielsen 	{
1193db522d3aSSimon L. B. Nielsen 	char *provname = NULL, *contname = NULL;
1194db522d3aSSimon L. B. Nielsen 	if (!pinfo)
1195db522d3aSSimon L. B. Nielsen 		{
1196db522d3aSSimon L. B. Nielsen 		BIO_printf(out, "  No Private Key\n");
1197db522d3aSSimon L. B. Nielsen 		return;
1198db522d3aSSimon L. B. Nielsen 		}
1199db522d3aSSimon L. B. Nielsen 	provname = wide_to_asc(pinfo->pwszProvName);
1200db522d3aSSimon L. B. Nielsen 	contname = wide_to_asc(pinfo->pwszContainerName);
1201db522d3aSSimon L. B. Nielsen 	if (!provname || !contname)
1202db522d3aSSimon L. B. Nielsen 		goto err;
1203db522d3aSSimon L. B. Nielsen 
1204db522d3aSSimon L. B. Nielsen 	BIO_printf(out, "  Private Key Info:\n");
1205db522d3aSSimon L. B. Nielsen 	BIO_printf(out, "    Provider Name:  %s, Provider Type %d\n", provname, pinfo->dwProvType);
1206db522d3aSSimon L. B. Nielsen 	BIO_printf(out, "    Container Name: %s, Key Type %d\n", contname, pinfo->dwKeySpec);
1207db522d3aSSimon L. B. Nielsen 	err:
1208db522d3aSSimon L. B. Nielsen 	if (provname)
1209db522d3aSSimon L. B. Nielsen 		OPENSSL_free(provname);
1210db522d3aSSimon L. B. Nielsen 	if (contname)
1211db522d3aSSimon L. B. Nielsen 		OPENSSL_free(contname);
1212db522d3aSSimon L. B. Nielsen 	}
1213db522d3aSSimon L. B. Nielsen 
1214db522d3aSSimon L. B. Nielsen char * capi_cert_get_fname(CAPI_CTX *ctx, PCCERT_CONTEXT cert)
1215db522d3aSSimon L. B. Nielsen 	{
1216db522d3aSSimon L. B. Nielsen 	LPWSTR wfname;
1217db522d3aSSimon L. B. Nielsen 	DWORD dlen;
1218db522d3aSSimon L. B. Nielsen 
1219db522d3aSSimon L. B. Nielsen 	CAPI_trace(ctx, "capi_cert_get_fname\n");
1220db522d3aSSimon L. B. Nielsen 	if (!CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID, NULL, &dlen))
1221db522d3aSSimon L. B. Nielsen 		return NULL;
1222db522d3aSSimon L. B. Nielsen 	wfname = OPENSSL_malloc(dlen);
1223db522d3aSSimon L. B. Nielsen 	if (CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID, wfname, &dlen))
1224db522d3aSSimon L. B. Nielsen 		{
1225db522d3aSSimon L. B. Nielsen 		char *fname = wide_to_asc(wfname);
1226db522d3aSSimon L. B. Nielsen 		OPENSSL_free(wfname);
1227db522d3aSSimon L. B. Nielsen 		return fname;
1228db522d3aSSimon L. B. Nielsen 		}
1229db522d3aSSimon L. B. Nielsen 	CAPIerr(CAPI_F_CAPI_CERT_GET_FNAME, CAPI_R_ERROR_GETTING_FRIENDLY_NAME);
1230db522d3aSSimon L. B. Nielsen 	capi_addlasterror();
1231db522d3aSSimon L. B. Nielsen 
1232db522d3aSSimon L. B. Nielsen 	OPENSSL_free(wfname);
1233db522d3aSSimon L. B. Nielsen 	return NULL;
1234db522d3aSSimon L. B. Nielsen 	}
1235db522d3aSSimon L. B. Nielsen 
1236db522d3aSSimon L. B. Nielsen 
1237db522d3aSSimon L. B. Nielsen void capi_dump_cert(CAPI_CTX *ctx, BIO *out, PCCERT_CONTEXT cert)
1238db522d3aSSimon L. B. Nielsen 	{
1239db522d3aSSimon L. B. Nielsen 	X509 *x;
1240db522d3aSSimon L. B. Nielsen 	unsigned char *p;
1241db522d3aSSimon L. B. Nielsen 	unsigned long flags = ctx->dump_flags;
1242db522d3aSSimon L. B. Nielsen 	if (flags & CAPI_DMP_FNAME)
1243db522d3aSSimon L. B. Nielsen 		{
1244db522d3aSSimon L. B. Nielsen 		char *fname;
1245db522d3aSSimon L. B. Nielsen 		fname = capi_cert_get_fname(ctx, cert);
1246db522d3aSSimon L. B. Nielsen 		if (fname)
1247db522d3aSSimon L. B. Nielsen 			{
1248db522d3aSSimon L. B. Nielsen 			BIO_printf(out, "  Friendly Name \"%s\"\n", fname);
1249db522d3aSSimon L. B. Nielsen 			OPENSSL_free(fname);
1250db522d3aSSimon L. B. Nielsen 			}
1251db522d3aSSimon L. B. Nielsen 		else
1252db522d3aSSimon L. B. Nielsen 			BIO_printf(out, "  <No Friendly Name>\n");
1253db522d3aSSimon L. B. Nielsen 		}
1254db522d3aSSimon L. B. Nielsen 
1255db522d3aSSimon L. B. Nielsen 	p = cert->pbCertEncoded;
1256db522d3aSSimon L. B. Nielsen 	x = d2i_X509(NULL, &p, cert->cbCertEncoded);
1257db522d3aSSimon L. B. Nielsen 	if (!x)
1258db522d3aSSimon L. B. Nielsen 		BIO_printf(out, "  <Can't parse certificate>\n");
1259db522d3aSSimon L. B. Nielsen 	if (flags & CAPI_DMP_SUMMARY)
1260db522d3aSSimon L. B. Nielsen 		{
1261db522d3aSSimon L. B. Nielsen 		BIO_printf(out, "  Subject: ");
1262db522d3aSSimon L. B. Nielsen 		X509_NAME_print_ex(out, X509_get_subject_name(x), 0, XN_FLAG_ONELINE);
1263db522d3aSSimon L. B. Nielsen 		BIO_printf(out, "\n  Issuer: ");
1264db522d3aSSimon L. B. Nielsen 		X509_NAME_print_ex(out, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE);
1265db522d3aSSimon L. B. Nielsen 		BIO_printf(out, "\n");
1266db522d3aSSimon L. B. Nielsen 		}
1267db522d3aSSimon L. B. Nielsen 	if (flags & CAPI_DMP_FULL)
1268db522d3aSSimon L. B. Nielsen 		X509_print_ex(out, x, XN_FLAG_ONELINE,0);
1269db522d3aSSimon L. B. Nielsen 
1270db522d3aSSimon L. B. Nielsen 	if (flags & CAPI_DMP_PKEYINFO)
1271db522d3aSSimon L. B. Nielsen 		{
1272db522d3aSSimon L. B. Nielsen 		CRYPT_KEY_PROV_INFO *pinfo;
1273db522d3aSSimon L. B. Nielsen 		pinfo = capi_get_prov_info(ctx, cert);
1274db522d3aSSimon L. B. Nielsen 		capi_dump_prov_info(ctx, out, pinfo);
1275db522d3aSSimon L. B. Nielsen 		if (pinfo)
1276db522d3aSSimon L. B. Nielsen 			OPENSSL_free(pinfo);
1277db522d3aSSimon L. B. Nielsen 		}
1278db522d3aSSimon L. B. Nielsen 
1279db522d3aSSimon L. B. Nielsen 	if (flags & CAPI_DMP_PEM)
1280db522d3aSSimon L. B. Nielsen 		PEM_write_bio_X509(out, x);
1281db522d3aSSimon L. B. Nielsen 	X509_free(x);
1282db522d3aSSimon L. B. Nielsen 	}
1283db522d3aSSimon L. B. Nielsen 
1284db522d3aSSimon L. B. Nielsen HCERTSTORE capi_open_store(CAPI_CTX *ctx, char *storename)
1285db522d3aSSimon L. B. Nielsen 	{
1286db522d3aSSimon L. B. Nielsen 	HCERTSTORE hstore;
1287db522d3aSSimon L. B. Nielsen 
1288db522d3aSSimon L. B. Nielsen 	if (!storename)
1289db522d3aSSimon L. B. Nielsen 		storename = ctx->storename;
1290db522d3aSSimon L. B. Nielsen 	if (!storename)
1291db522d3aSSimon L. B. Nielsen 		storename = "MY";
1292db522d3aSSimon L. B. Nielsen 	CAPI_trace(ctx, "Opening certificate store %s\n", storename);
1293db522d3aSSimon L. B. Nielsen 
1294db522d3aSSimon L. B. Nielsen 	hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0,
1295db522d3aSSimon L. B. Nielsen 				ctx->store_flags, storename);
1296db522d3aSSimon L. B. Nielsen 	if (!hstore)
1297db522d3aSSimon L. B. Nielsen 		{
1298db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_OPEN_STORE, CAPI_R_ERROR_OPENING_STORE);
1299db522d3aSSimon L. B. Nielsen 		capi_addlasterror();
1300db522d3aSSimon L. B. Nielsen 		}
1301db522d3aSSimon L. B. Nielsen 	return hstore;
1302db522d3aSSimon L. B. Nielsen 	}
1303db522d3aSSimon L. B. Nielsen 
1304db522d3aSSimon L. B. Nielsen int capi_list_certs(CAPI_CTX *ctx, BIO *out, char *id)
1305db522d3aSSimon L. B. Nielsen 	{
1306db522d3aSSimon L. B. Nielsen 	char *storename;
1307db522d3aSSimon L. B. Nielsen 	int idx;
1308db522d3aSSimon L. B. Nielsen 	int ret = 1;
1309db522d3aSSimon L. B. Nielsen 	HCERTSTORE hstore;
1310db522d3aSSimon L. B. Nielsen 	PCCERT_CONTEXT cert = NULL;
1311db522d3aSSimon L. B. Nielsen 
1312db522d3aSSimon L. B. Nielsen 	storename = ctx->storename;
1313db522d3aSSimon L. B. Nielsen 	if (!storename)
1314db522d3aSSimon L. B. Nielsen 		storename = "MY";
1315db522d3aSSimon L. B. Nielsen 	CAPI_trace(ctx, "Listing certs for store %s\n", storename);
1316db522d3aSSimon L. B. Nielsen 
1317db522d3aSSimon L. B. Nielsen 	hstore = capi_open_store(ctx, storename);
1318db522d3aSSimon L. B. Nielsen 	if (!hstore)
1319db522d3aSSimon L. B. Nielsen 		return 0;
1320db522d3aSSimon L. B. Nielsen 	if (id)
1321db522d3aSSimon L. B. Nielsen 		{
1322db522d3aSSimon L. B. Nielsen 		cert = capi_find_cert(ctx, id, hstore);
1323db522d3aSSimon L. B. Nielsen 		if (!cert)
1324db522d3aSSimon L. B. Nielsen 			{
1325db522d3aSSimon L. B. Nielsen 			ret = 0;
1326db522d3aSSimon L. B. Nielsen 			goto err;
1327db522d3aSSimon L. B. Nielsen 			}
1328db522d3aSSimon L. B. Nielsen 		capi_dump_cert(ctx, out, cert);
1329db522d3aSSimon L. B. Nielsen 		CertFreeCertificateContext(cert);
1330db522d3aSSimon L. B. Nielsen 		}
1331db522d3aSSimon L. B. Nielsen 	else
1332db522d3aSSimon L. B. Nielsen 		{
1333db522d3aSSimon L. B. Nielsen 		for(idx = 0;;idx++)
1334db522d3aSSimon L. B. Nielsen 			{
1335db522d3aSSimon L. B. Nielsen 			LPWSTR fname = NULL;
1336db522d3aSSimon L. B. Nielsen 			cert = CertEnumCertificatesInStore(hstore, cert);
1337db522d3aSSimon L. B. Nielsen 			if (!cert)
1338db522d3aSSimon L. B. Nielsen 				break;
1339db522d3aSSimon L. B. Nielsen 			BIO_printf(out, "Certificate %d\n", idx);
1340db522d3aSSimon L. B. Nielsen 			capi_dump_cert(ctx, out, cert);
1341db522d3aSSimon L. B. Nielsen 			}
1342db522d3aSSimon L. B. Nielsen 		}
1343db522d3aSSimon L. B. Nielsen 	err:
1344db522d3aSSimon L. B. Nielsen 	CertCloseStore(hstore, 0);
1345db522d3aSSimon L. B. Nielsen 	return ret;
1346db522d3aSSimon L. B. Nielsen 	}
1347db522d3aSSimon L. B. Nielsen 
1348db522d3aSSimon L. B. Nielsen static PCCERT_CONTEXT capi_find_cert(CAPI_CTX *ctx, const char *id, HCERTSTORE hstore)
1349db522d3aSSimon L. B. Nielsen 	{
1350db522d3aSSimon L. B. Nielsen 	PCCERT_CONTEXT cert = NULL;
1351db522d3aSSimon L. B. Nielsen 	char *fname = NULL;
1352db522d3aSSimon L. B. Nielsen 	int match;
1353db522d3aSSimon L. B. Nielsen 	switch(ctx->lookup_method)
1354db522d3aSSimon L. B. Nielsen 		{
1355db522d3aSSimon L. B. Nielsen 		case CAPI_LU_SUBSTR:
1356db522d3aSSimon L. B. Nielsen 			return CertFindCertificateInStore(hstore,
1357db522d3aSSimon L. B. Nielsen 					X509_ASN_ENCODING, 0,
1358db522d3aSSimon L. B. Nielsen 					CERT_FIND_SUBJECT_STR_A, id, NULL);
1359db522d3aSSimon L. B. Nielsen 		case CAPI_LU_FNAME:
1360db522d3aSSimon L. B. Nielsen 			for(;;)
1361db522d3aSSimon L. B. Nielsen 				{
1362db522d3aSSimon L. B. Nielsen 				cert = CertEnumCertificatesInStore(hstore, cert);
1363db522d3aSSimon L. B. Nielsen 				if (!cert)
1364db522d3aSSimon L. B. Nielsen 					return NULL;
1365db522d3aSSimon L. B. Nielsen 				fname = capi_cert_get_fname(ctx, cert);
1366db522d3aSSimon L. B. Nielsen 				if (fname)
1367db522d3aSSimon L. B. Nielsen 					{
1368db522d3aSSimon L. B. Nielsen 					if (strcmp(fname, id))
1369db522d3aSSimon L. B. Nielsen 						match = 0;
1370db522d3aSSimon L. B. Nielsen 					else
1371db522d3aSSimon L. B. Nielsen 						match = 1;
1372db522d3aSSimon L. B. Nielsen 					OPENSSL_free(fname);
1373db522d3aSSimon L. B. Nielsen 					if (match)
1374db522d3aSSimon L. B. Nielsen 						return cert;
1375db522d3aSSimon L. B. Nielsen 					}
1376db522d3aSSimon L. B. Nielsen 				}
1377db522d3aSSimon L. B. Nielsen 		default:
1378db522d3aSSimon L. B. Nielsen 			return NULL;
1379db522d3aSSimon L. B. Nielsen 		}
1380db522d3aSSimon L. B. Nielsen 	}
1381db522d3aSSimon L. B. Nielsen 
1382db522d3aSSimon L. B. Nielsen static CAPI_KEY *capi_get_key(CAPI_CTX *ctx, const char *contname, char *provname, DWORD ptype, DWORD keyspec)
1383db522d3aSSimon L. B. Nielsen 	{
1384db522d3aSSimon L. B. Nielsen 	CAPI_KEY *key;
1385db522d3aSSimon L. B. Nielsen 	key = OPENSSL_malloc(sizeof(CAPI_KEY));
1386db522d3aSSimon L. B. Nielsen 	CAPI_trace(ctx, "capi_get_key, contname=%s, provname=%s, type=%d\n",
1387db522d3aSSimon L. B. Nielsen 						contname, provname, ptype);
1388db522d3aSSimon L. B. Nielsen 	if (!CryptAcquireContext(&key->hprov, contname, provname, ptype, 0))
1389db522d3aSSimon L. B. Nielsen 		{
1390db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_CRYPTACQUIRECONTEXT_ERROR);
1391db522d3aSSimon L. B. Nielsen 		capi_addlasterror();
1392db522d3aSSimon L. B. Nielsen 		goto err;
1393db522d3aSSimon L. B. Nielsen 		}
1394db522d3aSSimon L. B. Nielsen 	if (!CryptGetUserKey(key->hprov, keyspec, &key->key))
1395db522d3aSSimon L. B. Nielsen 		{
1396db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_GETUSERKEY_ERROR);
1397db522d3aSSimon L. B. Nielsen 		capi_addlasterror();
1398db522d3aSSimon L. B. Nielsen 		CryptReleaseContext(key->hprov, 0);
1399db522d3aSSimon L. B. Nielsen 		goto err;
1400db522d3aSSimon L. B. Nielsen 		}
1401db522d3aSSimon L. B. Nielsen 	key->keyspec = keyspec;
1402db522d3aSSimon L. B. Nielsen 	key->pcert = NULL;
1403db522d3aSSimon L. B. Nielsen 	return key;
1404db522d3aSSimon L. B. Nielsen 
1405db522d3aSSimon L. B. Nielsen 	err:
1406db522d3aSSimon L. B. Nielsen 	OPENSSL_free(key);
1407db522d3aSSimon L. B. Nielsen 	return NULL;
1408db522d3aSSimon L. B. Nielsen 	}
1409db522d3aSSimon L. B. Nielsen 
1410db522d3aSSimon L. B. Nielsen static CAPI_KEY *capi_get_cert_key(CAPI_CTX *ctx, PCCERT_CONTEXT cert)
1411db522d3aSSimon L. B. Nielsen 	{
1412db522d3aSSimon L. B. Nielsen 	CAPI_KEY *key = NULL;
1413db522d3aSSimon L. B. Nielsen 	CRYPT_KEY_PROV_INFO *pinfo = NULL;
1414db522d3aSSimon L. B. Nielsen 	char *provname = NULL, *contname = NULL;
1415db522d3aSSimon L. B. Nielsen 	pinfo = capi_get_prov_info(ctx, cert);
1416db522d3aSSimon L. B. Nielsen 	if (!pinfo)
1417db522d3aSSimon L. B. Nielsen 		goto err;
1418db522d3aSSimon L. B. Nielsen 	provname = wide_to_asc(pinfo->pwszProvName);
1419db522d3aSSimon L. B. Nielsen 	contname = wide_to_asc(pinfo->pwszContainerName);
1420db522d3aSSimon L. B. Nielsen 	if (!provname || !contname)
1421db522d3aSSimon L. B. Nielsen 		goto err;
1422db522d3aSSimon L. B. Nielsen 	key = capi_get_key(ctx, contname, provname,
1423db522d3aSSimon L. B. Nielsen 				pinfo->dwProvType, pinfo->dwKeySpec);
1424db522d3aSSimon L. B. Nielsen 
1425db522d3aSSimon L. B. Nielsen 	err:
1426db522d3aSSimon L. B. Nielsen 	if (pinfo)
1427db522d3aSSimon L. B. Nielsen 		OPENSSL_free(pinfo);
1428db522d3aSSimon L. B. Nielsen 	if (provname)
1429db522d3aSSimon L. B. Nielsen 		OPENSSL_free(provname);
1430db522d3aSSimon L. B. Nielsen 	if (contname)
1431db522d3aSSimon L. B. Nielsen 		OPENSSL_free(contname);
1432db522d3aSSimon L. B. Nielsen 	return key;
1433db522d3aSSimon L. B. Nielsen 	}
1434db522d3aSSimon L. B. Nielsen 
1435db522d3aSSimon L. B. Nielsen CAPI_KEY *capi_find_key(CAPI_CTX *ctx, const char *id)
1436db522d3aSSimon L. B. Nielsen 	{
1437db522d3aSSimon L. B. Nielsen 	PCCERT_CONTEXT cert;
1438db522d3aSSimon L. B. Nielsen 	HCERTSTORE hstore;
1439db522d3aSSimon L. B. Nielsen 	CAPI_KEY *key = NULL;
1440db522d3aSSimon L. B. Nielsen 	switch (ctx->lookup_method)
1441db522d3aSSimon L. B. Nielsen 		{
1442db522d3aSSimon L. B. Nielsen 		case CAPI_LU_SUBSTR:
1443db522d3aSSimon L. B. Nielsen 		case CAPI_LU_FNAME:
1444db522d3aSSimon L. B. Nielsen 		hstore = capi_open_store(ctx, NULL);
1445db522d3aSSimon L. B. Nielsen 		if (!hstore)
1446db522d3aSSimon L. B. Nielsen 			return NULL;
1447db522d3aSSimon L. B. Nielsen 		cert = capi_find_cert(ctx, id, hstore);
1448db522d3aSSimon L. B. Nielsen 		if (cert)
1449db522d3aSSimon L. B. Nielsen 			{
1450db522d3aSSimon L. B. Nielsen 			key = capi_get_cert_key(ctx, cert);
1451db522d3aSSimon L. B. Nielsen 			CertFreeCertificateContext(cert);
1452db522d3aSSimon L. B. Nielsen 			}
1453db522d3aSSimon L. B. Nielsen 		CertCloseStore(hstore, 0);
1454db522d3aSSimon L. B. Nielsen 		break;
1455db522d3aSSimon L. B. Nielsen 
1456db522d3aSSimon L. B. Nielsen 		case CAPI_LU_CONTNAME:
1457db522d3aSSimon L. B. Nielsen 		key = capi_get_key(ctx, id, ctx->cspname, ctx->csptype,
1458db522d3aSSimon L. B. Nielsen 							ctx->keytype);
1459db522d3aSSimon L. B. Nielsen 		break;
1460db522d3aSSimon L. B. Nielsen 		}
1461db522d3aSSimon L. B. Nielsen 
1462db522d3aSSimon L. B. Nielsen 	return key;
1463db522d3aSSimon L. B. Nielsen 	}
1464db522d3aSSimon L. B. Nielsen 
1465db522d3aSSimon L. B. Nielsen void capi_free_key(CAPI_KEY *key)
1466db522d3aSSimon L. B. Nielsen 	{
1467db522d3aSSimon L. B. Nielsen 	if (!key)
1468db522d3aSSimon L. B. Nielsen 		return;
1469db522d3aSSimon L. B. Nielsen 	CryptDestroyKey(key->key);
1470db522d3aSSimon L. B. Nielsen 	CryptReleaseContext(key->hprov, 0);
1471db522d3aSSimon L. B. Nielsen 	if (key->pcert)
1472db522d3aSSimon L. B. Nielsen 		CertFreeCertificateContext(key->pcert);
1473db522d3aSSimon L. B. Nielsen 	OPENSSL_free(key);
1474db522d3aSSimon L. B. Nielsen 	}
1475db522d3aSSimon L. B. Nielsen 
1476db522d3aSSimon L. B. Nielsen 
1477db522d3aSSimon L. B. Nielsen /* Initialize a CAPI_CTX structure */
1478db522d3aSSimon L. B. Nielsen 
1479db522d3aSSimon L. B. Nielsen static CAPI_CTX *capi_ctx_new()
1480db522d3aSSimon L. B. Nielsen 	{
1481db522d3aSSimon L. B. Nielsen 	CAPI_CTX *ctx;
1482db522d3aSSimon L. B. Nielsen 	ctx = OPENSSL_malloc(sizeof(CAPI_CTX));
1483db522d3aSSimon L. B. Nielsen 	if (!ctx)
1484db522d3aSSimon L. B. Nielsen 		{
1485db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CAPI_CTX_NEW, ERR_R_MALLOC_FAILURE);
1486db522d3aSSimon L. B. Nielsen 		return NULL;
1487db522d3aSSimon L. B. Nielsen 		}
1488db522d3aSSimon L. B. Nielsen 	ctx->cspname = NULL;
1489db522d3aSSimon L. B. Nielsen 	ctx->csptype = PROV_RSA_FULL;
1490db522d3aSSimon L. B. Nielsen 	ctx->dump_flags = CAPI_DMP_SUMMARY|CAPI_DMP_FNAME;
1491db522d3aSSimon L. B. Nielsen 	ctx->keytype = AT_KEYEXCHANGE;
1492db522d3aSSimon L. B. Nielsen 	ctx->storename = NULL;
1493db522d3aSSimon L. B. Nielsen 	ctx->ssl_client_store = NULL;
1494db522d3aSSimon L. B. Nielsen 	ctx->store_flags = CERT_STORE_OPEN_EXISTING_FLAG |
1495db522d3aSSimon L. B. Nielsen 				CERT_STORE_READONLY_FLAG |
1496db522d3aSSimon L. B. Nielsen 				CERT_SYSTEM_STORE_CURRENT_USER;
1497db522d3aSSimon L. B. Nielsen 	ctx->lookup_method = CAPI_LU_SUBSTR;
1498db522d3aSSimon L. B. Nielsen 	ctx->debug_level = 0;
1499db522d3aSSimon L. B. Nielsen 	ctx->debug_file = NULL;
1500db522d3aSSimon L. B. Nielsen 	ctx->client_cert_select = cert_select_simple;
1501db522d3aSSimon L. B. Nielsen 	return ctx;
1502db522d3aSSimon L. B. Nielsen 	}
1503db522d3aSSimon L. B. Nielsen 
1504db522d3aSSimon L. B. Nielsen static void capi_ctx_free(CAPI_CTX *ctx)
1505db522d3aSSimon L. B. Nielsen 	{
1506db522d3aSSimon L. B. Nielsen 	CAPI_trace(ctx, "Calling capi_ctx_free with %lx\n", ctx);
1507db522d3aSSimon L. B. Nielsen 	if (!ctx)
1508db522d3aSSimon L. B. Nielsen 		return;
1509db522d3aSSimon L. B. Nielsen 	if (ctx->cspname)
1510db522d3aSSimon L. B. Nielsen 		OPENSSL_free(ctx->cspname);
1511db522d3aSSimon L. B. Nielsen 	if (ctx->debug_file)
1512db522d3aSSimon L. B. Nielsen 		OPENSSL_free(ctx->debug_file);
1513db522d3aSSimon L. B. Nielsen 	if (ctx->storename)
1514db522d3aSSimon L. B. Nielsen 		OPENSSL_free(ctx->storename);
1515db522d3aSSimon L. B. Nielsen 	if (ctx->ssl_client_store)
1516db522d3aSSimon L. B. Nielsen 		OPENSSL_free(ctx->ssl_client_store);
1517db522d3aSSimon L. B. Nielsen 	OPENSSL_free(ctx);
1518db522d3aSSimon L. B. Nielsen 	}
1519db522d3aSSimon L. B. Nielsen 
1520db522d3aSSimon L. B. Nielsen static int capi_ctx_set_provname(CAPI_CTX *ctx, LPSTR pname, DWORD type, int check)
1521db522d3aSSimon L. B. Nielsen 	{
1522db522d3aSSimon L. B. Nielsen 	CAPI_trace(ctx, "capi_ctx_set_provname, name=%s, type=%d\n", pname, type);
1523db522d3aSSimon L. B. Nielsen 	if (check)
1524db522d3aSSimon L. B. Nielsen 		{
1525db522d3aSSimon L. B. Nielsen 		HCRYPTPROV hprov;
1526db522d3aSSimon L. B. Nielsen 		if (!CryptAcquireContext(&hprov, NULL, pname, type,
1527db522d3aSSimon L. B. Nielsen 						CRYPT_VERIFYCONTEXT))
1528db522d3aSSimon L. B. Nielsen 			{
1529db522d3aSSimon L. B. Nielsen 			CAPIerr(CAPI_F_CAPI_CTX_SET_PROVNAME, CAPI_R_CRYPTACQUIRECONTEXT_ERROR);
1530db522d3aSSimon L. B. Nielsen 			capi_addlasterror();
1531db522d3aSSimon L. B. Nielsen 			return 0;
1532db522d3aSSimon L. B. Nielsen 			}
1533db522d3aSSimon L. B. Nielsen 		CryptReleaseContext(hprov, 0);
1534db522d3aSSimon L. B. Nielsen 		}
1535db522d3aSSimon L. B. Nielsen 	ctx->cspname = BUF_strdup(pname);
1536db522d3aSSimon L. B. Nielsen 	ctx->csptype = type;
1537db522d3aSSimon L. B. Nielsen 	return 1;
1538db522d3aSSimon L. B. Nielsen 	}
1539db522d3aSSimon L. B. Nielsen 
1540db522d3aSSimon L. B. Nielsen static int capi_ctx_set_provname_idx(CAPI_CTX *ctx, int idx)
1541db522d3aSSimon L. B. Nielsen 	{
1542db522d3aSSimon L. B. Nielsen 	LPSTR pname;
1543db522d3aSSimon L. B. Nielsen 	DWORD type;
1544db522d3aSSimon L. B. Nielsen 	if (capi_get_provname(ctx, &pname, &type, idx) != 1)
1545db522d3aSSimon L. B. Nielsen 		return 0;
1546db522d3aSSimon L. B. Nielsen 	return capi_ctx_set_provname(ctx, pname, type, 0);
1547db522d3aSSimon L. B. Nielsen 	}
1548db522d3aSSimon L. B. Nielsen 
1549db522d3aSSimon L. B. Nielsen static int cert_issuer_match(STACK_OF(X509_NAME) *ca_dn, X509 *x)
1550db522d3aSSimon L. B. Nielsen 	{
1551db522d3aSSimon L. B. Nielsen 	int i;
1552db522d3aSSimon L. B. Nielsen 	X509_NAME *nm;
1553db522d3aSSimon L. B. Nielsen 	/* Special case: empty list: match anything */
1554db522d3aSSimon L. B. Nielsen 	if (sk_X509_NAME_num(ca_dn) <= 0)
1555db522d3aSSimon L. B. Nielsen 		return 1;
1556db522d3aSSimon L. B. Nielsen 	for (i = 0; i < sk_X509_NAME_num(ca_dn); i++)
1557db522d3aSSimon L. B. Nielsen 		{
1558db522d3aSSimon L. B. Nielsen 		nm = sk_X509_NAME_value(ca_dn, i);
1559db522d3aSSimon L. B. Nielsen 		if (!X509_NAME_cmp(nm, X509_get_issuer_name(x)))
1560db522d3aSSimon L. B. Nielsen 				return 1;
1561db522d3aSSimon L. B. Nielsen 		}
1562db522d3aSSimon L. B. Nielsen 	return 0;
1563db522d3aSSimon L. B. Nielsen 	}
1564db522d3aSSimon L. B. Nielsen 
1565db522d3aSSimon L. B. Nielsen 
1566db522d3aSSimon L. B. Nielsen 
1567db522d3aSSimon L. B. Nielsen static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl,
1568db522d3aSSimon L. B. Nielsen 	STACK_OF(X509_NAME) *ca_dn, X509 **pcert, EVP_PKEY **pkey,
1569db522d3aSSimon L. B. Nielsen 	STACK_OF(X509) **pother, UI_METHOD *ui_method, void *callback_data)
1570db522d3aSSimon L. B. Nielsen 	{
1571db522d3aSSimon L. B. Nielsen 	STACK_OF(X509) *certs = NULL;
1572db522d3aSSimon L. B. Nielsen 	X509 *x;
1573db522d3aSSimon L. B. Nielsen 	char *storename;
1574db522d3aSSimon L. B. Nielsen 	const char *p;
1575db522d3aSSimon L. B. Nielsen 	int i, client_cert_idx;
1576db522d3aSSimon L. B. Nielsen 	HCERTSTORE hstore;
1577db522d3aSSimon L. B. Nielsen 	PCCERT_CONTEXT cert = NULL, excert = NULL;
1578db522d3aSSimon L. B. Nielsen 	CAPI_CTX *ctx;
1579db522d3aSSimon L. B. Nielsen 	CAPI_KEY *key;
1580db522d3aSSimon L. B. Nielsen 	ctx = ENGINE_get_ex_data(e, capi_idx);
1581db522d3aSSimon L. B. Nielsen 
1582db522d3aSSimon L. B. Nielsen 	*pcert = NULL;
1583db522d3aSSimon L. B. Nielsen 	*pkey = NULL;
1584db522d3aSSimon L. B. Nielsen 
1585db522d3aSSimon L. B. Nielsen 	storename = ctx->ssl_client_store;
1586db522d3aSSimon L. B. Nielsen 	if (!storename)
1587db522d3aSSimon L. B. Nielsen 		storename = "MY";
1588db522d3aSSimon L. B. Nielsen 
1589db522d3aSSimon L. B. Nielsen 	hstore = capi_open_store(ctx, storename);
1590db522d3aSSimon L. B. Nielsen 	if (!hstore)
1591db522d3aSSimon L. B. Nielsen 		return 0;
1592db522d3aSSimon L. B. Nielsen 	/* Enumerate all certificates collect any matches */
1593db522d3aSSimon L. B. Nielsen 	for(i = 0;;i++)
1594db522d3aSSimon L. B. Nielsen 		{
1595db522d3aSSimon L. B. Nielsen 		cert = CertEnumCertificatesInStore(hstore, cert);
1596db522d3aSSimon L. B. Nielsen 		if (!cert)
1597db522d3aSSimon L. B. Nielsen 			break;
1598db522d3aSSimon L. B. Nielsen 		p = cert->pbCertEncoded;
1599db522d3aSSimon L. B. Nielsen 		x = d2i_X509(NULL, &p, cert->cbCertEncoded);
1600db522d3aSSimon L. B. Nielsen 		if (!x)
1601db522d3aSSimon L. B. Nielsen 			{
1602db522d3aSSimon L. B. Nielsen 			CAPI_trace(ctx, "Can't Parse Certificate %d\n", i);
1603db522d3aSSimon L. B. Nielsen 			continue;
1604db522d3aSSimon L. B. Nielsen 			}
1605db522d3aSSimon L. B. Nielsen 		if (cert_issuer_match(ca_dn, x)
1606db522d3aSSimon L. B. Nielsen 			&& X509_check_purpose(x, X509_PURPOSE_SSL_CLIENT, 0))
1607db522d3aSSimon L. B. Nielsen 			{
1608db522d3aSSimon L. B. Nielsen 			key = capi_get_cert_key(ctx, cert);
1609db522d3aSSimon L. B. Nielsen 			if (!key)
1610db522d3aSSimon L. B. Nielsen 				{
1611db522d3aSSimon L. B. Nielsen 				X509_free(x);
1612db522d3aSSimon L. B. Nielsen 				continue;
1613db522d3aSSimon L. B. Nielsen 				}
1614db522d3aSSimon L. B. Nielsen 			/* Match found: attach extra data to it so
1615db522d3aSSimon L. B. Nielsen 			 * we can retrieve the key later.
1616db522d3aSSimon L. B. Nielsen 			 */
1617db522d3aSSimon L. B. Nielsen 			excert = CertDuplicateCertificateContext(cert);
1618db522d3aSSimon L. B. Nielsen 			key->pcert = excert;
1619db522d3aSSimon L. B. Nielsen 			X509_set_ex_data(x, cert_capi_idx, key);
1620db522d3aSSimon L. B. Nielsen 
1621db522d3aSSimon L. B. Nielsen 			if (!certs)
1622db522d3aSSimon L. B. Nielsen 				certs = sk_X509_new_null();
1623db522d3aSSimon L. B. Nielsen 
1624db522d3aSSimon L. B. Nielsen 			sk_X509_push(certs, x);
1625db522d3aSSimon L. B. Nielsen 			}
1626db522d3aSSimon L. B. Nielsen 		else
1627db522d3aSSimon L. B. Nielsen 			X509_free(x);
1628db522d3aSSimon L. B. Nielsen 
1629db522d3aSSimon L. B. Nielsen 		}
1630db522d3aSSimon L. B. Nielsen 
1631db522d3aSSimon L. B. Nielsen 	if (cert)
1632db522d3aSSimon L. B. Nielsen 		CertFreeCertificateContext(cert);
1633db522d3aSSimon L. B. Nielsen 	if (hstore)
1634db522d3aSSimon L. B. Nielsen 		CertCloseStore(hstore, 0);
1635db522d3aSSimon L. B. Nielsen 
1636db522d3aSSimon L. B. Nielsen 	if (!certs)
1637db522d3aSSimon L. B. Nielsen 		return 0;
1638db522d3aSSimon L. B. Nielsen 
1639db522d3aSSimon L. B. Nielsen 
1640db522d3aSSimon L. B. Nielsen 	/* Select the appropriate certificate */
1641db522d3aSSimon L. B. Nielsen 
1642db522d3aSSimon L. B. Nielsen 	client_cert_idx = ctx->client_cert_select(e, ssl, certs);
1643db522d3aSSimon L. B. Nielsen 
1644db522d3aSSimon L. B. Nielsen 	/* Set the selected certificate and free the rest */
1645db522d3aSSimon L. B. Nielsen 
1646db522d3aSSimon L. B. Nielsen 	for(i = 0; i < sk_X509_num(certs); i++)
1647db522d3aSSimon L. B. Nielsen 		{
1648db522d3aSSimon L. B. Nielsen 		x = sk_X509_value(certs, i);
1649db522d3aSSimon L. B. Nielsen 		if (i == client_cert_idx)
1650db522d3aSSimon L. B. Nielsen 			*pcert = x;
1651db522d3aSSimon L. B. Nielsen 		else
1652db522d3aSSimon L. B. Nielsen 			{
1653db522d3aSSimon L. B. Nielsen 			key = X509_get_ex_data(x, cert_capi_idx);
1654db522d3aSSimon L. B. Nielsen 			capi_free_key(key);
1655db522d3aSSimon L. B. Nielsen 			X509_free(x);
1656db522d3aSSimon L. B. Nielsen 			}
1657db522d3aSSimon L. B. Nielsen 		}
1658db522d3aSSimon L. B. Nielsen 
1659db522d3aSSimon L. B. Nielsen 	sk_X509_free(certs);
1660db522d3aSSimon L. B. Nielsen 
1661db522d3aSSimon L. B. Nielsen 	if (!*pcert)
1662db522d3aSSimon L. B. Nielsen 		return 0;
1663db522d3aSSimon L. B. Nielsen 
1664db522d3aSSimon L. B. Nielsen 	/* Setup key for selected certificate */
1665db522d3aSSimon L. B. Nielsen 
1666db522d3aSSimon L. B. Nielsen 	key = X509_get_ex_data(*pcert, cert_capi_idx);
1667db522d3aSSimon L. B. Nielsen 	*pkey = capi_get_pkey(e, key);
1668db522d3aSSimon L. B. Nielsen 	X509_set_ex_data(*pcert, cert_capi_idx, NULL);
1669db522d3aSSimon L. B. Nielsen 
1670db522d3aSSimon L. B. Nielsen 	return 1;
1671db522d3aSSimon L. B. Nielsen 
1672db522d3aSSimon L. B. Nielsen 	}
1673db522d3aSSimon L. B. Nielsen 
1674db522d3aSSimon L. B. Nielsen 
1675db522d3aSSimon L. B. Nielsen /* Simple client cert selection function: always select first */
1676db522d3aSSimon L. B. Nielsen 
1677db522d3aSSimon L. B. Nielsen static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs)
1678db522d3aSSimon L. B. Nielsen 	{
1679db522d3aSSimon L. B. Nielsen 	return 0;
1680db522d3aSSimon L. B. Nielsen 	}
1681db522d3aSSimon L. B. Nielsen 
1682db522d3aSSimon L. B. Nielsen #ifdef OPENSSL_CAPIENG_DIALOG
1683db522d3aSSimon L. B. Nielsen 
1684db522d3aSSimon L. B. Nielsen /* More complex cert selection function, using standard function
1685db522d3aSSimon L. B. Nielsen  * CryptUIDlgSelectCertificateFromStore() to produce a dialog box.
1686db522d3aSSimon L. B. Nielsen  */
1687db522d3aSSimon L. B. Nielsen 
1688db522d3aSSimon L. B. Nielsen /* Definitions which are in cryptuiapi.h but this is not present in older
1689db522d3aSSimon L. B. Nielsen  * versions of headers.
1690db522d3aSSimon L. B. Nielsen  */
1691db522d3aSSimon L. B. Nielsen 
1692db522d3aSSimon L. B. Nielsen #ifndef CRYPTUI_SELECT_LOCATION_COLUMN
1693db522d3aSSimon L. B. Nielsen #define CRYPTUI_SELECT_LOCATION_COLUMN                   0x000000010
1694db522d3aSSimon L. B. Nielsen #define CRYPTUI_SELECT_INTENDEDUSE_COLUMN                0x000000004
1695db522d3aSSimon L. B. Nielsen #endif
1696db522d3aSSimon L. B. Nielsen 
1697db522d3aSSimon L. B. Nielsen #define dlg_title L"OpenSSL Application SSL Client Certificate Selection"
1698db522d3aSSimon L. B. Nielsen #define dlg_prompt L"Select a certificate to use for authentication"
1699db522d3aSSimon L. B. Nielsen #define dlg_columns	 CRYPTUI_SELECT_LOCATION_COLUMN \
1700db522d3aSSimon L. B. Nielsen 			|CRYPTUI_SELECT_INTENDEDUSE_COLUMN
1701db522d3aSSimon L. B. Nielsen 
1702db522d3aSSimon L. B. Nielsen static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs)
1703db522d3aSSimon L. B. Nielsen 	{
1704db522d3aSSimon L. B. Nielsen 	X509 *x;
1705db522d3aSSimon L. B. Nielsen 	HCERTSTORE dstore;
1706db522d3aSSimon L. B. Nielsen 	PCCERT_CONTEXT cert;
1707db522d3aSSimon L. B. Nielsen 	CAPI_CTX *ctx;
1708db522d3aSSimon L. B. Nielsen 	CAPI_KEY *key;
1709db522d3aSSimon L. B. Nielsen 	HWND hwnd;
1710db522d3aSSimon L. B. Nielsen 	int i, idx = -1;
1711db522d3aSSimon L. B. Nielsen 	if (sk_X509_num(certs) == 1)
1712db522d3aSSimon L. B. Nielsen 		return 0;
1713db522d3aSSimon L. B. Nielsen 	ctx = ENGINE_get_ex_data(e, capi_idx);
1714db522d3aSSimon L. B. Nielsen 	/* Create an in memory store of certificates */
1715db522d3aSSimon L. B. Nielsen 	dstore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1716db522d3aSSimon L. B. Nielsen 					CERT_STORE_CREATE_NEW_FLAG, NULL);
1717db522d3aSSimon L. B. Nielsen 	if (!dstore)
1718db522d3aSSimon L. B. Nielsen 		{
1719db522d3aSSimon L. B. Nielsen 		CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_CREATING_STORE);
1720db522d3aSSimon L. B. Nielsen 		capi_addlasterror();
1721db522d3aSSimon L. B. Nielsen 		goto err;
1722db522d3aSSimon L. B. Nielsen 		}
1723db522d3aSSimon L. B. Nielsen 	/* Add all certificates to store */
1724db522d3aSSimon L. B. Nielsen 	for(i = 0; i < sk_X509_num(certs); i++)
1725db522d3aSSimon L. B. Nielsen 		{
1726db522d3aSSimon L. B. Nielsen 		x = sk_X509_value(certs, i);
1727db522d3aSSimon L. B. Nielsen 		key = X509_get_ex_data(x, cert_capi_idx);
1728db522d3aSSimon L. B. Nielsen 
1729db522d3aSSimon L. B. Nielsen 		if (!CertAddCertificateContextToStore(dstore, key->pcert,
1730db522d3aSSimon L. B. Nielsen 						CERT_STORE_ADD_NEW, NULL))
1731db522d3aSSimon L. B. Nielsen 			{
1732db522d3aSSimon L. B. Nielsen 			CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_ADDING_CERT);
1733db522d3aSSimon L. B. Nielsen 			capi_addlasterror();
1734db522d3aSSimon L. B. Nielsen 			goto err;
1735db522d3aSSimon L. B. Nielsen 			}
1736db522d3aSSimon L. B. Nielsen 
1737db522d3aSSimon L. B. Nielsen 		}
1738db522d3aSSimon L. B. Nielsen 	hwnd = GetForegroundWindow();
1739db522d3aSSimon L. B. Nielsen 	if (!hwnd)
1740db522d3aSSimon L. B. Nielsen 		hwnd = GetActiveWindow();
1741db522d3aSSimon L. B. Nielsen 	if (!hwnd && ctx->getconswindow)
1742db522d3aSSimon L. B. Nielsen 		hwnd = ctx->getconswindow();
1743db522d3aSSimon L. B. Nielsen 	/* Call dialog to select one */
1744db522d3aSSimon L. B. Nielsen 	cert = ctx->certselectdlg(dstore, hwnd, dlg_title, dlg_prompt,
1745db522d3aSSimon L. B. Nielsen 						dlg_columns, 0, NULL);
1746db522d3aSSimon L. B. Nielsen 
1747db522d3aSSimon L. B. Nielsen 	/* Find matching cert from list */
1748db522d3aSSimon L. B. Nielsen 	if (cert)
1749db522d3aSSimon L. B. Nielsen 		{
1750db522d3aSSimon L. B. Nielsen 		for(i = 0; i < sk_X509_num(certs); i++)
1751db522d3aSSimon L. B. Nielsen 			{
1752db522d3aSSimon L. B. Nielsen 			x = sk_X509_value(certs, i);
1753db522d3aSSimon L. B. Nielsen 			key = X509_get_ex_data(x, cert_capi_idx);
1754db522d3aSSimon L. B. Nielsen 			if (CertCompareCertificate(
1755db522d3aSSimon L. B. Nielsen 				X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
1756db522d3aSSimon L. B. Nielsen 					cert->pCertInfo,
1757db522d3aSSimon L. B. Nielsen 					key->pcert->pCertInfo))
1758db522d3aSSimon L. B. Nielsen 				{
1759db522d3aSSimon L. B. Nielsen 				idx = i;
1760db522d3aSSimon L. B. Nielsen 				break;
1761db522d3aSSimon L. B. Nielsen 				}
1762db522d3aSSimon L. B. Nielsen 			}
1763db522d3aSSimon L. B. Nielsen 		}
1764db522d3aSSimon L. B. Nielsen 
1765db522d3aSSimon L. B. Nielsen 	err:
1766db522d3aSSimon L. B. Nielsen 	if (dstore)
1767db522d3aSSimon L. B. Nielsen 		CertCloseStore(dstore, 0);
1768db522d3aSSimon L. B. Nielsen 	return idx;
1769db522d3aSSimon L. B. Nielsen 
1770db522d3aSSimon L. B. Nielsen 	}
1771db522d3aSSimon L. B. Nielsen #endif
1772db522d3aSSimon L. B. Nielsen 
1773db522d3aSSimon L. B. Nielsen #endif
1774db522d3aSSimon L. B. Nielsen #else /* !WIN32 */
1775db522d3aSSimon L. B. Nielsen #include <openssl/engine.h>
1776db522d3aSSimon L. B. Nielsen #ifndef OPENSSL_NO_DYNAMIC_ENGINE
1777db522d3aSSimon L. B. Nielsen OPENSSL_EXPORT
1778db522d3aSSimon L. B. Nielsen int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) { return 0; }
1779db522d3aSSimon L. B. Nielsen IMPLEMENT_DYNAMIC_CHECK_FN()
1780db522d3aSSimon L. B. Nielsen #endif
1781db522d3aSSimon L. B. Nielsen #endif
1782