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