xref: /netbsd-src/crypto/external/bsd/openssl/dist/engines/e_capi.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
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 	capi_idx = ENGINE_get_ex_new_index(0, NULL, NULL, NULL, 0);
446 	cert_capi_idx = X509_get_ex_new_index(0, NULL, NULL, NULL, 0);
447 
448 	ctx = capi_ctx_new();
449 	if (!ctx || (capi_idx < 0))
450 		goto memerr;
451 
452 	ENGINE_set_ex_data(e, capi_idx, ctx);
453 	/* Setup RSA_METHOD */
454 	rsa_capi_idx = RSA_get_ex_new_index(0, NULL, NULL, NULL, 0);
455 	ossl_rsa_meth = RSA_PKCS1_SSLeay();
456 	capi_rsa_method.rsa_pub_enc = ossl_rsa_meth->rsa_pub_enc;
457 	capi_rsa_method.rsa_pub_dec = ossl_rsa_meth->rsa_pub_dec;
458 	capi_rsa_method.rsa_mod_exp = ossl_rsa_meth->rsa_mod_exp;
459 	capi_rsa_method.bn_mod_exp = ossl_rsa_meth->bn_mod_exp;
460 
461 	/* Setup DSA Method */
462 	dsa_capi_idx = DSA_get_ex_new_index(0, NULL, NULL, NULL, 0);
463 	ossl_dsa_meth = DSA_OpenSSL();
464 	capi_dsa_method.dsa_do_verify = ossl_dsa_meth->dsa_do_verify;
465 	capi_dsa_method.dsa_mod_exp = ossl_dsa_meth->dsa_mod_exp;
466 	capi_dsa_method.bn_mod_exp = ossl_dsa_meth->bn_mod_exp;
467 
468 #ifdef OPENSSL_CAPIENG_DIALOG
469 	{
470 	HMODULE cryptui = LoadLibrary(TEXT("CRYPTUI.DLL"));
471 	HMODULE kernel = GetModuleHandle(TEXT("KERNEL32.DLL"));
472 	if (cryptui)
473 		ctx->certselectdlg = (CERTDLG)GetProcAddress(cryptui, "CryptUIDlgSelectCertificateFromStore");
474 	if (kernel)
475 		ctx->getconswindow = (GETCONSWIN)GetProcAddress(kernel, "GetConsoleWindow");
476 	if (cryptui && !OPENSSL_isservice())
477 		ctx->client_cert_select = cert_select_dialog;
478 	}
479 #endif
480 
481 
482 	return 1;
483 
484 	memerr:
485 	CAPIerr(CAPI_F_CAPI_INIT, ERR_R_MALLOC_FAILURE);
486 	return 0;
487 
488 	return 1;
489 	}
490 
491 static int capi_destroy(ENGINE *e)
492 	{
493 	ERR_unload_CAPI_strings();
494 	return 1;
495 	}
496 
497 static int capi_finish(ENGINE *e)
498 	{
499 	CAPI_CTX *ctx;
500 	ctx = ENGINE_get_ex_data(e, capi_idx);
501 	capi_ctx_free(ctx);
502 	ENGINE_set_ex_data(e, capi_idx, NULL);
503 	return 1;
504 	}
505 
506 
507 /* CryptoAPI key application data. This contains
508  * a handle to the private key container (for sign operations)
509  * and a handle to the key (for decrypt operations).
510  */
511 
512 struct CAPI_KEY_st
513 	{
514 	/* Associated certificate context (if any) */
515 	PCCERT_CONTEXT pcert;
516 	HCRYPTPROV hprov;
517 	HCRYPTKEY key;
518 	DWORD keyspec;
519 	};
520 
521 static int bind_capi(ENGINE *e)
522 	{
523 	if (!ENGINE_set_id(e, engine_capi_id)
524 		|| !ENGINE_set_name(e, engine_capi_name)
525 		|| !ENGINE_set_flags(e, ENGINE_FLAGS_NO_REGISTER_ALL)
526 		|| !ENGINE_set_init_function(e, capi_init)
527 		|| !ENGINE_set_finish_function(e, capi_finish)
528 		|| !ENGINE_set_destroy_function(e, capi_destroy)
529 		|| !ENGINE_set_RSA(e, &capi_rsa_method)
530 		|| !ENGINE_set_DSA(e, &capi_dsa_method)
531 		|| !ENGINE_set_load_privkey_function(e, capi_load_privkey)
532 		|| !ENGINE_set_load_ssl_client_cert_function(e,
533 						capi_load_ssl_client_cert)
534 		|| !ENGINE_set_cmd_defns(e, capi_cmd_defns)
535 		|| !ENGINE_set_ctrl_function(e, capi_ctrl))
536 			return 0;
537 	ERR_load_CAPI_strings();
538 
539 	return 1;
540 
541 	}
542 
543 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
544 static int bind_helper(ENGINE *e, const char *id)
545 	{
546 	if(id && (strcmp(id, engine_capi_id) != 0))
547 		return 0;
548 	if(!bind_capi(e))
549 		return 0;
550 	return 1;
551 	}
552 IMPLEMENT_DYNAMIC_CHECK_FN()
553 IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
554 #else
555 static ENGINE *engine_capi(void)
556 	{
557 	ENGINE *ret = ENGINE_new();
558 	if(!ret)
559 		return NULL;
560 	if(!bind_capi(ret))
561 		{
562 		ENGINE_free(ret);
563 		return NULL;
564 		}
565 	return ret;
566 	}
567 
568 void ENGINE_load_capi(void)
569 	{
570 	/* Copied from eng_[openssl|dyn].c */
571 	ENGINE *toadd = engine_capi();
572 	if(!toadd) return;
573 	ENGINE_add(toadd);
574 	ENGINE_free(toadd);
575 	ERR_clear_error();
576 	}
577 #endif
578 
579 
580 static int lend_tobn(BIGNUM *bn, unsigned char *bin, int binlen)
581 	{
582 	int i;
583 	/* Reverse buffer in place: since this is a keyblob structure
584 	 * that will be freed up after conversion anyway it doesn't
585 	 * matter if we change it.
586 	 */
587 	for(i = 0; i < binlen / 2; i++)
588 		{
589 		unsigned char c;
590 		c = bin[i];
591 		bin[i] = bin[binlen - i - 1];
592 		bin[binlen - i - 1] = c;
593 		}
594 
595 	if (!BN_bin2bn(bin, binlen, bn))
596 		return 0;
597 	return 1;
598 	}
599 
600 /* Given a CAPI_KEY get an EVP_PKEY structure */
601 
602 static EVP_PKEY *capi_get_pkey(ENGINE *eng, CAPI_KEY *key)
603 	{
604 	unsigned char *pubkey = NULL;
605 	DWORD len;
606 	BLOBHEADER *bh;
607 	RSA *rkey = NULL;
608 	DSA *dkey = NULL;
609 	EVP_PKEY *ret = NULL;
610 	if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, NULL, &len))
611 		{
612 		CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_LENGTH_ERROR);
613 		capi_addlasterror();
614 		return NULL;
615 		}
616 
617 	pubkey = OPENSSL_malloc(len);
618 
619 	if (!pubkey)
620 		goto memerr;
621 
622 	if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, pubkey, &len))
623 		{
624 		CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_ERROR);
625 		capi_addlasterror();
626 		goto err;
627 		}
628 
629 	bh = (BLOBHEADER *)pubkey;
630 	if (bh->bType != PUBLICKEYBLOB)
631 		{
632 		CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_PUBLIC_KEY_BLOB);
633 		goto err;
634 		}
635 	if (bh->aiKeyAlg == CALG_RSA_SIGN || bh->aiKeyAlg == CALG_RSA_KEYX)
636 		{
637 		RSAPUBKEY *rp;
638 		DWORD rsa_modlen;
639 		unsigned char *rsa_modulus;
640 		rp = (RSAPUBKEY *)(bh + 1);
641 		if (rp->magic != 0x31415352)
642 			{
643 			char magstr[10];
644 			BIO_snprintf(magstr, 10, "%lx", rp->magic);
645 			CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_RSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER);
646 			ERR_add_error_data(2, "magic=0x", magstr);
647 			goto err;
648 			}
649 		rsa_modulus = (unsigned char *)(rp + 1);
650 		rkey = RSA_new_method(eng);
651 		if (!rkey)
652 			goto memerr;
653 
654 		rkey->e = BN_new();
655 		rkey->n = BN_new();
656 
657 		if (!rkey->e || !rkey->n)
658 			goto memerr;
659 
660 		if (!BN_set_word(rkey->e, rp->pubexp))
661 			goto memerr;
662 
663 		rsa_modlen = rp->bitlen / 8;
664 		if (!lend_tobn(rkey->n, rsa_modulus, rsa_modlen))
665 			goto memerr;
666 
667 		RSA_set_ex_data(rkey, rsa_capi_idx, key);
668 
669 		if (!(ret = EVP_PKEY_new()))
670 			goto memerr;
671 
672 		EVP_PKEY_assign_RSA(ret, rkey);
673 		rkey = NULL;
674 
675 		}
676 	else if (bh->aiKeyAlg == CALG_DSS_SIGN)
677 		{
678 		DSSPUBKEY *dp;
679 		DWORD dsa_plen;
680 		unsigned char *btmp;
681 		dp = (DSSPUBKEY *)(bh + 1);
682 		if (dp->magic != 0x31535344)
683 			{
684 			char magstr[10];
685 			BIO_snprintf(magstr, 10, "%lx", dp->magic);
686 			CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_DSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER);
687 			ERR_add_error_data(2, "magic=0x", magstr);
688 			goto err;
689 			}
690 		dsa_plen = dp->bitlen / 8;
691 		btmp = (unsigned char *)(dp + 1);
692 		dkey = DSA_new_method(eng);
693 		if (!dkey)
694 			goto memerr;
695 		dkey->p = BN_new();
696 		dkey->q = BN_new();
697 		dkey->g = BN_new();
698 		dkey->pub_key = BN_new();
699 		if (!dkey->p || !dkey->q || !dkey->g || !dkey->pub_key)
700 			goto memerr;
701 		if (!lend_tobn(dkey->p, btmp, dsa_plen))
702 			goto memerr;
703 		btmp += dsa_plen;
704 		if (!lend_tobn(dkey->q, btmp, 20))
705 			goto memerr;
706 		btmp += 20;
707 		if (!lend_tobn(dkey->g, btmp, dsa_plen))
708 			goto memerr;
709 		btmp += dsa_plen;
710 		if (!lend_tobn(dkey->pub_key, btmp, dsa_plen))
711 			goto memerr;
712 		btmp += dsa_plen;
713 
714 		DSA_set_ex_data(dkey, dsa_capi_idx, key);
715 
716 		if (!(ret = EVP_PKEY_new()))
717 			goto memerr;
718 
719 		EVP_PKEY_assign_DSA(ret, dkey);
720 		dkey = NULL;
721 		}
722 	else
723 		{
724 		char algstr[10];
725 		BIO_snprintf(algstr, 10, "%lx", bh->aiKeyAlg);
726 		CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_UNSUPPORTED_PUBLIC_KEY_ALGORITHM);
727 		ERR_add_error_data(2, "aiKeyAlg=0x", algstr);
728 		goto err;
729 		}
730 
731 
732 	err:
733 	if (pubkey)
734 		OPENSSL_free(pubkey);
735 	if (!ret)
736 		{
737 		if (rkey)
738 			RSA_free(rkey);
739 		if (dkey)
740 			DSA_free(dkey);
741 		}
742 
743 	return ret;
744 
745 memerr:
746 	CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_MALLOC_FAILURE);
747 	goto err;
748 
749 	}
750 
751 static EVP_PKEY *capi_load_privkey(ENGINE *eng, const char *key_id,
752 	UI_METHOD *ui_method, void *callback_data)
753 	{
754 	CAPI_CTX *ctx;
755 	CAPI_KEY *key;
756 	EVP_PKEY *ret;
757 	ctx = ENGINE_get_ex_data(eng, capi_idx);
758 
759 	if (!ctx)
760 		{
761 		CAPIerr(CAPI_F_CAPI_LOAD_PRIVKEY, CAPI_R_CANT_FIND_CAPI_CONTEXT);
762 		return NULL;
763 		}
764 
765 	key = capi_find_key(ctx, key_id);
766 
767 	if (!key)
768 		return NULL;
769 
770 	ret = capi_get_pkey(eng, key);
771 
772 	if (!ret)
773 		capi_free_key(key);
774 	return ret;
775 
776 	}
777 
778 /* CryptoAPI RSA operations */
779 
780 int capi_rsa_priv_enc(int flen, const unsigned char *from,
781                 unsigned char *to, RSA *rsa, int padding)
782 	{
783 	CAPIerr(CAPI_F_CAPI_RSA_PRIV_ENC, CAPI_R_FUNCTION_NOT_SUPPORTED);
784 	return -1;
785 	}
786 
787 int capi_rsa_sign(int dtype, const unsigned char *m, unsigned int m_len,
788              unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
789 	{
790 	ALG_ID alg;
791 	HCRYPTHASH hash;
792 	DWORD slen;
793 	unsigned int i;
794 	int ret = -1;
795 	CAPI_KEY *capi_key;
796 	CAPI_CTX *ctx;
797 
798 	ctx = ENGINE_get_ex_data(rsa->engine, capi_idx);
799 
800 	CAPI_trace(ctx, "Called CAPI_rsa_sign()\n");
801 
802 	capi_key = RSA_get_ex_data(rsa, rsa_capi_idx);
803 	if (!capi_key)
804 		{
805 		CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_GET_KEY);
806 		return -1;
807 		}
808 /* Convert the signature type to a CryptoAPI algorithm ID */
809 	switch(dtype)
810 		{
811 	case NID_sha1:
812 		alg = CALG_SHA1;
813 		break;
814 
815 	case NID_md5:
816 		alg = CALG_MD5;
817 		break;
818 
819 	case NID_md5_sha1:
820 		alg = CALG_SSL3_SHAMD5;
821 		break;
822 	default:
823 		{
824 		char algstr[10];
825 		BIO_snprintf(algstr, 10, "%lx", dtype);
826 		CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_UNSUPPORTED_ALGORITHM_NID);
827 		ERR_add_error_data(2, "NID=0x", algstr);
828 		return -1;
829 		}
830 	}
831 
832 
833 
834 /* Create the hash object */
835 	if(!CryptCreateHash(capi_key->hprov, alg, 0, 0, &hash))
836 		{
837 		CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT);
838 		capi_addlasterror();
839 		return -1;
840 		}
841 /* Set the hash value to the value passed */
842 
843 	if(!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)m, 0))
844 		{
845 		CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_SET_HASH_VALUE);
846 		capi_addlasterror();
847 		goto err;
848 		}
849 
850 
851 /* Finally sign it */
852 	slen = RSA_size(rsa);
853 	if(!CryptSignHashA(hash, capi_key->keyspec, NULL, 0, sigret, &slen))
854 		{
855 		CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_ERROR_SIGNING_HASH);
856 		capi_addlasterror();
857 		goto err;
858 		}
859 	else
860 		{
861 		ret = 1;
862 		/* Inplace byte reversal of signature */
863 		for(i = 0; i < slen / 2; i++)
864 			{
865 			unsigned char c;
866 			c = sigret[i];
867 			sigret[i] = sigret[slen - i - 1];
868 			sigret[slen - i - 1] = c;
869 			}
870 		*siglen = slen;
871 		}
872 
873 	/* Now cleanup */
874 
875 err:
876 	CryptDestroyHash(hash);
877 
878 	return ret;
879 	}
880 
881 int capi_rsa_priv_dec(int flen, const unsigned char *from,
882                 unsigned char *to, RSA *rsa, int padding)
883 	{
884 	int i;
885 	unsigned char *tmpbuf;
886 	CAPI_KEY *capi_key;
887 	CAPI_CTX *ctx;
888 	ctx = ENGINE_get_ex_data(rsa->engine, capi_idx);
889 
890 	CAPI_trace(ctx, "Called capi_rsa_priv_dec()\n");
891 
892 
893 	capi_key = RSA_get_ex_data(rsa, rsa_capi_idx);
894 	if (!capi_key)
895 		{
896 		CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_CANT_GET_KEY);
897 		return -1;
898 		}
899 
900 	if(padding != RSA_PKCS1_PADDING)
901 		{
902 		char errstr[10];
903 		BIO_snprintf(errstr, 10, "%d", padding);
904 		CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_UNSUPPORTED_PADDING);
905 		ERR_add_error_data(2, "padding=", errstr);
906 		return -1;
907 		}
908 
909 	/* Create temp reverse order version of input */
910 	if(!(tmpbuf = OPENSSL_malloc(flen)) )
911 		{
912 		CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, ERR_R_MALLOC_FAILURE);
913 		return -1;
914 		}
915 	for(i = 0; i < flen; i++)
916 		tmpbuf[flen - i - 1] = from[i];
917 
918 	/* Finally decrypt it */
919 	if(!CryptDecrypt(capi_key->key, 0, TRUE, 0, tmpbuf, &flen))
920 		{
921 		CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_DECRYPT_ERROR);
922 		capi_addlasterror();
923 		OPENSSL_free(tmpbuf);
924 		return -1;
925 		}
926 	else memcpy(to, tmpbuf, flen);
927 
928 	OPENSSL_free(tmpbuf);
929 
930 	return flen;
931 	}
932 
933 static int capi_rsa_free(RSA *rsa)
934 	{
935 	CAPI_KEY *capi_key;
936 	capi_key = RSA_get_ex_data(rsa, rsa_capi_idx);
937 	capi_free_key(capi_key);
938 	RSA_set_ex_data(rsa, rsa_capi_idx, 0);
939 	return 1;
940 	}
941 
942 /* CryptoAPI DSA operations */
943 
944 static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen,
945 								DSA *dsa)
946 	{
947 	HCRYPTHASH hash;
948 	DWORD slen;
949 	DSA_SIG *ret = NULL;
950 	CAPI_KEY *capi_key;
951 	CAPI_CTX *ctx;
952 	unsigned char csigbuf[40];
953 
954 	ctx = ENGINE_get_ex_data(dsa->engine, capi_idx);
955 
956 	CAPI_trace(ctx, "Called CAPI_dsa_do_sign()\n");
957 
958 	capi_key = DSA_get_ex_data(dsa, dsa_capi_idx);
959 
960 	if (!capi_key)
961 		{
962 		CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_GET_KEY);
963 		return NULL;
964 		}
965 
966 	if (dlen != 20)
967 		{
968 		CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_INVALID_DIGEST_LENGTH);
969 		return NULL;
970 		}
971 
972 	/* Create the hash object */
973 	if(!CryptCreateHash(capi_key->hprov, CALG_SHA1, 0, 0, &hash))
974 		{
975 		CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT);
976 		capi_addlasterror();
977 		return NULL;
978 		}
979 
980 	/* Set the hash value to the value passed */
981 	if(!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)digest, 0))
982 		{
983 		CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_SET_HASH_VALUE);
984 		capi_addlasterror();
985 		goto err;
986 		}
987 
988 
989 	/* Finally sign it */
990 	slen = sizeof(csigbuf);
991 	if(!CryptSignHashA(hash, capi_key->keyspec, NULL, 0, csigbuf, &slen))
992 		{
993 		CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_ERROR_SIGNING_HASH);
994 		capi_addlasterror();
995 		goto err;
996 		}
997 	else
998 		{
999 		ret = DSA_SIG_new();
1000 		if (!ret)
1001 			goto err;
1002 		ret->r = BN_new();
1003 		ret->s = BN_new();
1004 		if (!ret->r || !ret->s)
1005 			goto err;
1006 		if (!lend_tobn(ret->r, csigbuf, 20)
1007 			|| !lend_tobn(ret->s, csigbuf + 20, 20))
1008 			{
1009 			DSA_SIG_free(ret);
1010 			ret = NULL;
1011 			goto err;
1012 			}
1013 		}
1014 
1015 	/* Now cleanup */
1016 
1017 err:
1018 	OPENSSL_cleanse(csigbuf, 40);
1019 	CryptDestroyHash(hash);
1020 	return ret;
1021 	}
1022 
1023 static int capi_dsa_free(DSA *dsa)
1024 	{
1025 	CAPI_KEY *capi_key;
1026 	capi_key = DSA_get_ex_data(dsa, dsa_capi_idx);
1027 	capi_free_key(capi_key);
1028 	DSA_set_ex_data(dsa, dsa_capi_idx, 0);
1029 	return 1;
1030 	}
1031 
1032 static void capi_vtrace(CAPI_CTX *ctx, int level, char *format, va_list argptr)
1033 	{
1034 	BIO *out;
1035 
1036 	if (!ctx || (ctx->debug_level < level) || (!ctx->debug_file))
1037 		return;
1038 	out = BIO_new_file(ctx->debug_file, "a+");
1039 	BIO_vprintf(out, format, argptr);
1040 	BIO_free(out);
1041 	}
1042 
1043 static void CAPI_trace(CAPI_CTX *ctx, char *format, ...)
1044 	{
1045 	va_list args;
1046 	va_start(args, format);
1047 	capi_vtrace(ctx, CAPI_DBG_TRACE, format, args);
1048 	va_end(args);
1049 	}
1050 
1051 static void capi_addlasterror(void)
1052 	{
1053 	capi_adderror(GetLastError());
1054 	}
1055 
1056 static void capi_adderror(DWORD err)
1057 	{
1058 	char errstr[10];
1059 	BIO_snprintf(errstr, 10, "%lX", err);
1060 	ERR_add_error_data(2, "Error code= 0x", errstr);
1061 	}
1062 
1063 static char *wide_to_asc(LPWSTR wstr)
1064 	{
1065 	char *str;
1066 	int len_0,sz;
1067 
1068 	if (!wstr)
1069 		return NULL;
1070 	len_0 = (int)wcslen(wstr)+1;	/* WideCharToMultiByte expects int */
1071         sz = WideCharToMultiByte(CP_ACP,0,wstr,len_0,NULL,0,NULL,NULL);
1072 	if (!sz)
1073 		{
1074 		CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_WIN32_ERROR);
1075 		return NULL;
1076 		}
1077 	str = OPENSSL_malloc(sz);
1078 	if (!str)
1079 		{
1080 		CAPIerr(CAPI_F_WIDE_TO_ASC, ERR_R_MALLOC_FAILURE);
1081 		return NULL;
1082 		}
1083 	if (!WideCharToMultiByte(CP_ACP,0,wstr,len_0,str,sz,NULL,NULL))
1084 		{
1085 		OPENSSL_free(str);
1086 		CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_WIN32_ERROR);
1087 		return NULL;
1088 		}
1089 	return str;
1090 	}
1091 
1092 static int capi_get_provname(CAPI_CTX *ctx, LPSTR *pname, DWORD *ptype, DWORD idx)
1093 	{
1094 	LPSTR name;
1095 	DWORD len, err;
1096 	CAPI_trace(ctx, "capi_get_provname, index=%d\n", idx);
1097 	if (!CryptEnumProvidersA(idx, NULL, 0, ptype, NULL, &len))
1098 		{
1099 		err = GetLastError();
1100 		if (err == ERROR_NO_MORE_ITEMS)
1101 			return 2;
1102 		CAPIerr(CAPI_F_CAPI_GET_PROVNAME, CAPI_R_CRYPTENUMPROVIDERS_ERROR);
1103 		capi_adderror(err);
1104 		return 0;
1105 		}
1106 	name = OPENSSL_malloc(len);
1107 	if (!CryptEnumProvidersA(idx, NULL, 0, ptype, name, &len))
1108 		{
1109 		err = GetLastError();
1110 		if (err == ERROR_NO_MORE_ITEMS)
1111 			return 2;
1112 		CAPIerr(CAPI_F_CAPI_GET_PROVNAME, CAPI_R_CRYPTENUMPROVIDERS_ERROR);
1113 		capi_adderror(err);
1114 		return 0;
1115 		}
1116 	*pname = name;
1117 	CAPI_trace(ctx, "capi_get_provname, returned name=%s, type=%d\n", name, *ptype);
1118 
1119 	return 1;
1120 	}
1121 
1122 static int capi_list_providers(CAPI_CTX *ctx, BIO *out)
1123 	{
1124 	DWORD idx, ptype;
1125 	int ret;
1126 	LPSTR provname = NULL;
1127 	CAPI_trace(ctx, "capi_list_providers\n");
1128 	BIO_printf(out, "Available CSPs:\n");
1129 	for(idx = 0; ; idx++)
1130 		{
1131 		ret = capi_get_provname(ctx, &provname, &ptype, idx);
1132 		if (ret == 2)
1133 			break;
1134 		if (ret == 0)
1135 			break;
1136 		BIO_printf(out, "%d. %s, type %d\n", idx, provname, ptype);
1137 		OPENSSL_free(provname);
1138 		}
1139 	return 1;
1140 	}
1141 
1142 static int capi_list_containers(CAPI_CTX *ctx, BIO *out)
1143 	{
1144 	int ret = 1;
1145 	HCRYPTPROV hprov;
1146 	DWORD err, idx, flags, buflen = 0, clen;
1147 	LPSTR cname;
1148 	CAPI_trace(ctx, "Listing containers CSP=%s, type = %d\n", ctx->cspname, ctx->csptype);
1149 	if (!CryptAcquireContextA(&hprov, NULL, ctx->cspname, ctx->csptype, CRYPT_VERIFYCONTEXT))
1150 		{
1151 		CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_CRYPTACQUIRECONTEXT_ERROR);
1152 		capi_addlasterror();
1153 		return 0;
1154 		}
1155 	if (!CryptGetProvParam(hprov, PP_ENUMCONTAINERS, NULL, &buflen, CRYPT_FIRST))
1156 		{
1157 		CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_ENUMCONTAINERS_ERROR);
1158 		capi_addlasterror();
1159 		return 0;
1160 		}
1161 	CAPI_trace(ctx, "Got max container len %d\n", buflen);
1162 	if (buflen == 0)
1163 		buflen = 1024;
1164 	cname = OPENSSL_malloc(buflen);
1165 	if (!cname)
1166 		{
1167 		CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, ERR_R_MALLOC_FAILURE);
1168 		goto err;
1169 		}
1170 
1171 	for (idx = 0;;idx++)
1172 		{
1173 		clen = buflen;
1174 		cname[0] = 0;
1175 
1176 		if (idx == 0)
1177 			flags = CRYPT_FIRST;
1178 		else
1179 			flags = 0;
1180 		if(!CryptGetProvParam(hprov, PP_ENUMCONTAINERS, cname, &clen, flags))
1181 			{
1182 			err = GetLastError();
1183 			if (err == ERROR_NO_MORE_ITEMS)
1184 				goto done;
1185 			CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_ENUMCONTAINERS_ERROR);
1186 			capi_adderror(err);
1187 			goto err;
1188 			}
1189 		CAPI_trace(ctx, "Container name %s, len=%d, index=%d, flags=%d\n", cname, clen, idx, flags);
1190 		if (!cname[0] && (clen == buflen))
1191 			{
1192 			CAPI_trace(ctx, "Enumerate bug: using workaround\n");
1193 			goto done;
1194 			}
1195 		BIO_printf(out, "%d. %s\n", idx, cname);
1196 		}
1197 	err:
1198 
1199 	ret = 0;
1200 
1201 	done:
1202 	if (cname)
1203 		OPENSSL_free(cname);
1204 	CryptReleaseContext(hprov, 0);
1205 
1206 	return ret;
1207 	}
1208 
1209 CRYPT_KEY_PROV_INFO *capi_get_prov_info(CAPI_CTX *ctx, PCCERT_CONTEXT cert)
1210 	{
1211 	DWORD len;
1212 	CRYPT_KEY_PROV_INFO *pinfo;
1213 
1214 	if(!CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &len))
1215 		return NULL;
1216 	pinfo = OPENSSL_malloc(len);
1217 	if (!pinfo)
1218 		{
1219 		CAPIerr(CAPI_F_CAPI_GET_PROV_INFO, ERR_R_MALLOC_FAILURE);
1220 		return NULL;
1221 		}
1222 	if(!CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, pinfo, &len))
1223 		{
1224 		CAPIerr(CAPI_F_CAPI_GET_PROV_INFO, CAPI_R_ERROR_GETTING_KEY_PROVIDER_INFO);
1225 		capi_addlasterror();
1226 		OPENSSL_free(pinfo);
1227 		return NULL;
1228 		}
1229 	return pinfo;
1230 	}
1231 
1232 static void capi_dump_prov_info(CAPI_CTX *ctx, BIO *out, CRYPT_KEY_PROV_INFO *pinfo)
1233 	{
1234 	char *provname = NULL, *contname = NULL;
1235 	if (!pinfo)
1236 		{
1237 		BIO_printf(out, "  No Private Key\n");
1238 		return;
1239 		}
1240 	provname = wide_to_asc(pinfo->pwszProvName);
1241 	contname = wide_to_asc(pinfo->pwszContainerName);
1242 	if (!provname || !contname)
1243 		goto err;
1244 
1245 	BIO_printf(out, "  Private Key Info:\n");
1246 	BIO_printf(out, "    Provider Name:  %s, Provider Type %d\n", provname, pinfo->dwProvType);
1247 	BIO_printf(out, "    Container Name: %s, Key Type %d\n", contname, pinfo->dwKeySpec);
1248 	err:
1249 	if (provname)
1250 		OPENSSL_free(provname);
1251 	if (contname)
1252 		OPENSSL_free(contname);
1253 	}
1254 
1255 char * capi_cert_get_fname(CAPI_CTX *ctx, PCCERT_CONTEXT cert)
1256 	{
1257 	LPWSTR wfname;
1258 	DWORD dlen;
1259 
1260 	CAPI_trace(ctx, "capi_cert_get_fname\n");
1261 	if (!CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID, NULL, &dlen))
1262 		return NULL;
1263 	wfname = OPENSSL_malloc(dlen);
1264 	if (CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID, wfname, &dlen))
1265 		{
1266 		char *fname = wide_to_asc(wfname);
1267 		OPENSSL_free(wfname);
1268 		return fname;
1269 		}
1270 	CAPIerr(CAPI_F_CAPI_CERT_GET_FNAME, CAPI_R_ERROR_GETTING_FRIENDLY_NAME);
1271 	capi_addlasterror();
1272 
1273 	OPENSSL_free(wfname);
1274 	return NULL;
1275 	}
1276 
1277 
1278 void capi_dump_cert(CAPI_CTX *ctx, BIO *out, PCCERT_CONTEXT cert)
1279 	{
1280 	X509 *x;
1281 	unsigned char *p;
1282 	unsigned long flags = ctx->dump_flags;
1283 	if (flags & CAPI_DMP_FNAME)
1284 		{
1285 		char *fname;
1286 		fname = capi_cert_get_fname(ctx, cert);
1287 		if (fname)
1288 			{
1289 			BIO_printf(out, "  Friendly Name \"%s\"\n", fname);
1290 			OPENSSL_free(fname);
1291 			}
1292 		else
1293 			BIO_printf(out, "  <No Friendly Name>\n");
1294 		}
1295 
1296 	p = cert->pbCertEncoded;
1297 	x = d2i_X509(NULL, &p, cert->cbCertEncoded);
1298 	if (!x)
1299 		BIO_printf(out, "  <Can't parse certificate>\n");
1300 	if (flags & CAPI_DMP_SUMMARY)
1301 		{
1302 		BIO_printf(out, "  Subject: ");
1303 		X509_NAME_print_ex(out, X509_get_subject_name(x), 0, XN_FLAG_ONELINE);
1304 		BIO_printf(out, "\n  Issuer: ");
1305 		X509_NAME_print_ex(out, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE);
1306 		BIO_printf(out, "\n");
1307 		}
1308 	if (flags & CAPI_DMP_FULL)
1309 		X509_print_ex(out, x, XN_FLAG_ONELINE,0);
1310 
1311 	if (flags & CAPI_DMP_PKEYINFO)
1312 		{
1313 		CRYPT_KEY_PROV_INFO *pinfo;
1314 		pinfo = capi_get_prov_info(ctx, cert);
1315 		capi_dump_prov_info(ctx, out, pinfo);
1316 		if (pinfo)
1317 			OPENSSL_free(pinfo);
1318 		}
1319 
1320 	if (flags & CAPI_DMP_PEM)
1321 		PEM_write_bio_X509(out, x);
1322 	X509_free(x);
1323 	}
1324 
1325 HCERTSTORE capi_open_store(CAPI_CTX *ctx, char *storename)
1326 	{
1327 	HCERTSTORE hstore;
1328 
1329 	if (!storename)
1330 		storename = ctx->storename;
1331 	if (!storename)
1332 		storename = "MY";
1333 	CAPI_trace(ctx, "Opening certificate store %s\n", storename);
1334 
1335 	hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0,
1336 				ctx->store_flags, storename);
1337 	if (!hstore)
1338 		{
1339 		CAPIerr(CAPI_F_CAPI_OPEN_STORE, CAPI_R_ERROR_OPENING_STORE);
1340 		capi_addlasterror();
1341 		}
1342 	return hstore;
1343 	}
1344 
1345 int capi_list_certs(CAPI_CTX *ctx, BIO *out, char *id)
1346 	{
1347 	char *storename;
1348 	int idx;
1349 	int ret = 1;
1350 	HCERTSTORE hstore;
1351 	PCCERT_CONTEXT cert = NULL;
1352 
1353 	storename = ctx->storename;
1354 	if (!storename)
1355 		storename = "MY";
1356 	CAPI_trace(ctx, "Listing certs for store %s\n", storename);
1357 
1358 	hstore = capi_open_store(ctx, storename);
1359 	if (!hstore)
1360 		return 0;
1361 	if (id)
1362 		{
1363 		cert = capi_find_cert(ctx, id, hstore);
1364 		if (!cert)
1365 			{
1366 			ret = 0;
1367 			goto err;
1368 			}
1369 		capi_dump_cert(ctx, out, cert);
1370 		CertFreeCertificateContext(cert);
1371 		}
1372 	else
1373 		{
1374 		for(idx = 0;;idx++)
1375 			{
1376 			LPWSTR fname = NULL;
1377 			cert = CertEnumCertificatesInStore(hstore, cert);
1378 			if (!cert)
1379 				break;
1380 			BIO_printf(out, "Certificate %d\n", idx);
1381 			capi_dump_cert(ctx, out, cert);
1382 			}
1383 		}
1384 	err:
1385 	CertCloseStore(hstore, 0);
1386 	return ret;
1387 	}
1388 
1389 static PCCERT_CONTEXT capi_find_cert(CAPI_CTX *ctx, const char *id, HCERTSTORE hstore)
1390 	{
1391 	PCCERT_CONTEXT cert = NULL;
1392 	char *fname = NULL;
1393 	int match;
1394 	switch(ctx->lookup_method)
1395 		{
1396 		case CAPI_LU_SUBSTR:
1397 			return CertFindCertificateInStore(hstore,
1398 					X509_ASN_ENCODING, 0,
1399 					CERT_FIND_SUBJECT_STR_A, id, NULL);
1400 		case CAPI_LU_FNAME:
1401 			for(;;)
1402 				{
1403 				cert = CertEnumCertificatesInStore(hstore, cert);
1404 				if (!cert)
1405 					return NULL;
1406 				fname = capi_cert_get_fname(ctx, cert);
1407 				if (fname)
1408 					{
1409 					if (strcmp(fname, id))
1410 						match = 0;
1411 					else
1412 						match = 1;
1413 					OPENSSL_free(fname);
1414 					if (match)
1415 						return cert;
1416 					}
1417 				}
1418 		default:
1419 			return NULL;
1420 		}
1421 	}
1422 
1423 static CAPI_KEY *capi_get_key(CAPI_CTX *ctx, const char *contname, char *provname, DWORD ptype, DWORD keyspec)
1424 	{
1425 	CAPI_KEY *key;
1426 	key = OPENSSL_malloc(sizeof(CAPI_KEY));
1427 	CAPI_trace(ctx, "capi_get_key, contname=%s, provname=%s, type=%d\n",
1428 						contname, provname, ptype);
1429 	if (!CryptAcquireContextA(&key->hprov, contname, provname, ptype, 0))
1430 		{
1431 		CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_CRYPTACQUIRECONTEXT_ERROR);
1432 		capi_addlasterror();
1433 		goto err;
1434 		}
1435 	if (!CryptGetUserKey(key->hprov, keyspec, &key->key))
1436 		{
1437 		CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_GETUSERKEY_ERROR);
1438 		capi_addlasterror();
1439 		CryptReleaseContext(key->hprov, 0);
1440 		goto err;
1441 		}
1442 	key->keyspec = keyspec;
1443 	key->pcert = NULL;
1444 	return key;
1445 
1446 	err:
1447 	OPENSSL_free(key);
1448 	return NULL;
1449 	}
1450 
1451 static CAPI_KEY *capi_get_cert_key(CAPI_CTX *ctx, PCCERT_CONTEXT cert)
1452 	{
1453 	CAPI_KEY *key = NULL;
1454 	CRYPT_KEY_PROV_INFO *pinfo = NULL;
1455 	char *provname = NULL, *contname = NULL;
1456 	pinfo = capi_get_prov_info(ctx, cert);
1457 	if (!pinfo)
1458 		goto err;
1459 	provname = wide_to_asc(pinfo->pwszProvName);
1460 	contname = wide_to_asc(pinfo->pwszContainerName);
1461 	if (!provname || !contname)
1462 		goto err;
1463 	key = capi_get_key(ctx, contname, provname,
1464 				pinfo->dwProvType, pinfo->dwKeySpec);
1465 
1466 	err:
1467 	if (pinfo)
1468 		OPENSSL_free(pinfo);
1469 	if (provname)
1470 		OPENSSL_free(provname);
1471 	if (contname)
1472 		OPENSSL_free(contname);
1473 	return key;
1474 	}
1475 
1476 CAPI_KEY *capi_find_key(CAPI_CTX *ctx, const char *id)
1477 	{
1478 	PCCERT_CONTEXT cert;
1479 	HCERTSTORE hstore;
1480 	CAPI_KEY *key = NULL;
1481 	switch (ctx->lookup_method)
1482 		{
1483 		case CAPI_LU_SUBSTR:
1484 		case CAPI_LU_FNAME:
1485 		hstore = capi_open_store(ctx, NULL);
1486 		if (!hstore)
1487 			return NULL;
1488 		cert = capi_find_cert(ctx, id, hstore);
1489 		if (cert)
1490 			{
1491 			key = capi_get_cert_key(ctx, cert);
1492 			CertFreeCertificateContext(cert);
1493 			}
1494 		CertCloseStore(hstore, 0);
1495 		break;
1496 
1497 		case CAPI_LU_CONTNAME:
1498 		key = capi_get_key(ctx, id, ctx->cspname, ctx->csptype,
1499 							ctx->keytype);
1500 		break;
1501 		}
1502 
1503 	return key;
1504 	}
1505 
1506 void capi_free_key(CAPI_KEY *key)
1507 	{
1508 	if (!key)
1509 		return;
1510 	CryptDestroyKey(key->key);
1511 	CryptReleaseContext(key->hprov, 0);
1512 	if (key->pcert)
1513 		CertFreeCertificateContext(key->pcert);
1514 	OPENSSL_free(key);
1515 	}
1516 
1517 
1518 /* Initialize a CAPI_CTX structure */
1519 
1520 static CAPI_CTX *capi_ctx_new()
1521 	{
1522 	CAPI_CTX *ctx;
1523 	ctx = OPENSSL_malloc(sizeof(CAPI_CTX));
1524 	if (!ctx)
1525 		{
1526 		CAPIerr(CAPI_F_CAPI_CTX_NEW, ERR_R_MALLOC_FAILURE);
1527 		return NULL;
1528 		}
1529 	ctx->cspname = NULL;
1530 	ctx->csptype = PROV_RSA_FULL;
1531 	ctx->dump_flags = CAPI_DMP_SUMMARY|CAPI_DMP_FNAME;
1532 	ctx->keytype = AT_KEYEXCHANGE;
1533 	ctx->storename = NULL;
1534 	ctx->ssl_client_store = NULL;
1535 	ctx->store_flags = CERT_STORE_OPEN_EXISTING_FLAG |
1536 				CERT_STORE_READONLY_FLAG |
1537 				CERT_SYSTEM_STORE_CURRENT_USER;
1538 	ctx->lookup_method = CAPI_LU_SUBSTR;
1539 	ctx->debug_level = 0;
1540 	ctx->debug_file = NULL;
1541 	ctx->client_cert_select = cert_select_simple;
1542 	return ctx;
1543 	}
1544 
1545 static void capi_ctx_free(CAPI_CTX *ctx)
1546 	{
1547 	CAPI_trace(ctx, "Calling capi_ctx_free with %lx\n", ctx);
1548 	if (!ctx)
1549 		return;
1550 	if (ctx->cspname)
1551 		OPENSSL_free(ctx->cspname);
1552 	if (ctx->debug_file)
1553 		OPENSSL_free(ctx->debug_file);
1554 	if (ctx->storename)
1555 		OPENSSL_free(ctx->storename);
1556 	if (ctx->ssl_client_store)
1557 		OPENSSL_free(ctx->ssl_client_store);
1558 	OPENSSL_free(ctx);
1559 	}
1560 
1561 static int capi_ctx_set_provname(CAPI_CTX *ctx, LPSTR pname, DWORD type, int check)
1562 	{
1563 	CAPI_trace(ctx, "capi_ctx_set_provname, name=%s, type=%d\n", pname, type);
1564 	if (check)
1565 		{
1566 		HCRYPTPROV hprov;
1567 		if (!CryptAcquireContextA(&hprov, NULL, pname, type,
1568 						CRYPT_VERIFYCONTEXT))
1569 			{
1570 			CAPIerr(CAPI_F_CAPI_CTX_SET_PROVNAME, CAPI_R_CRYPTACQUIRECONTEXT_ERROR);
1571 			capi_addlasterror();
1572 			return 0;
1573 			}
1574 		CryptReleaseContext(hprov, 0);
1575 		}
1576 	ctx->cspname = BUF_strdup(pname);
1577 	ctx->csptype = type;
1578 	return 1;
1579 	}
1580 
1581 static int capi_ctx_set_provname_idx(CAPI_CTX *ctx, int idx)
1582 	{
1583 	LPSTR pname;
1584 	DWORD type;
1585 	if (capi_get_provname(ctx, &pname, &type, idx) != 1)
1586 		return 0;
1587 	return capi_ctx_set_provname(ctx, pname, type, 0);
1588 	}
1589 
1590 static int cert_issuer_match(STACK_OF(X509_NAME) *ca_dn, X509 *x)
1591 	{
1592 	int i;
1593 	X509_NAME *nm;
1594 	/* Special case: empty list: match anything */
1595 	if (sk_X509_NAME_num(ca_dn) <= 0)
1596 		return 1;
1597 	for (i = 0; i < sk_X509_NAME_num(ca_dn); i++)
1598 		{
1599 		nm = sk_X509_NAME_value(ca_dn, i);
1600 		if (!X509_NAME_cmp(nm, X509_get_issuer_name(x)))
1601 				return 1;
1602 		}
1603 	return 0;
1604 	}
1605 
1606 
1607 
1608 static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl,
1609 	STACK_OF(X509_NAME) *ca_dn, X509 **pcert, EVP_PKEY **pkey,
1610 	STACK_OF(X509) **pother, UI_METHOD *ui_method, void *callback_data)
1611 	{
1612 	STACK_OF(X509) *certs = NULL;
1613 	X509 *x;
1614 	char *storename;
1615 	const char *p;
1616 	int i, client_cert_idx;
1617 	HCERTSTORE hstore;
1618 	PCCERT_CONTEXT cert = NULL, excert = NULL;
1619 	CAPI_CTX *ctx;
1620 	CAPI_KEY *key;
1621 	ctx = ENGINE_get_ex_data(e, capi_idx);
1622 
1623 	*pcert = NULL;
1624 	*pkey = NULL;
1625 
1626 	storename = ctx->ssl_client_store;
1627 	if (!storename)
1628 		storename = "MY";
1629 
1630 	hstore = capi_open_store(ctx, storename);
1631 	if (!hstore)
1632 		return 0;
1633 	/* Enumerate all certificates collect any matches */
1634 	for(i = 0;;i++)
1635 		{
1636 		cert = CertEnumCertificatesInStore(hstore, cert);
1637 		if (!cert)
1638 			break;
1639 		p = cert->pbCertEncoded;
1640 		x = d2i_X509(NULL, &p, cert->cbCertEncoded);
1641 		if (!x)
1642 			{
1643 			CAPI_trace(ctx, "Can't Parse Certificate %d\n", i);
1644 			continue;
1645 			}
1646 		if (cert_issuer_match(ca_dn, x)
1647 			&& X509_check_purpose(x, X509_PURPOSE_SSL_CLIENT, 0))
1648 			{
1649 			key = capi_get_cert_key(ctx, cert);
1650 			if (!key)
1651 				{
1652 				X509_free(x);
1653 				continue;
1654 				}
1655 			/* Match found: attach extra data to it so
1656 			 * we can retrieve the key later.
1657 			 */
1658 			excert = CertDuplicateCertificateContext(cert);
1659 			key->pcert = excert;
1660 			X509_set_ex_data(x, cert_capi_idx, key);
1661 
1662 			if (!certs)
1663 				certs = sk_X509_new_null();
1664 
1665 			sk_X509_push(certs, x);
1666 			}
1667 		else
1668 			X509_free(x);
1669 
1670 		}
1671 
1672 	if (cert)
1673 		CertFreeCertificateContext(cert);
1674 	if (hstore)
1675 		CertCloseStore(hstore, 0);
1676 
1677 	if (!certs)
1678 		return 0;
1679 
1680 
1681 	/* Select the appropriate certificate */
1682 
1683 	client_cert_idx = ctx->client_cert_select(e, ssl, certs);
1684 
1685 	/* Set the selected certificate and free the rest */
1686 
1687 	for(i = 0; i < sk_X509_num(certs); i++)
1688 		{
1689 		x = sk_X509_value(certs, i);
1690 		if (i == client_cert_idx)
1691 			*pcert = x;
1692 		else
1693 			{
1694 			key = X509_get_ex_data(x, cert_capi_idx);
1695 			capi_free_key(key);
1696 			X509_free(x);
1697 			}
1698 		}
1699 
1700 	sk_X509_free(certs);
1701 
1702 	if (!*pcert)
1703 		return 0;
1704 
1705 	/* Setup key for selected certificate */
1706 
1707 	key = X509_get_ex_data(*pcert, cert_capi_idx);
1708 	*pkey = capi_get_pkey(e, key);
1709 	X509_set_ex_data(*pcert, cert_capi_idx, NULL);
1710 
1711 	return 1;
1712 
1713 	}
1714 
1715 
1716 /* Simple client cert selection function: always select first */
1717 
1718 static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs)
1719 	{
1720 	return 0;
1721 	}
1722 
1723 #ifdef OPENSSL_CAPIENG_DIALOG
1724 
1725 /* More complex cert selection function, using standard function
1726  * CryptUIDlgSelectCertificateFromStore() to produce a dialog box.
1727  */
1728 
1729 /* Definitions which are in cryptuiapi.h but this is not present in older
1730  * versions of headers.
1731  */
1732 
1733 #ifndef CRYPTUI_SELECT_LOCATION_COLUMN
1734 #define CRYPTUI_SELECT_LOCATION_COLUMN                   0x000000010
1735 #define CRYPTUI_SELECT_INTENDEDUSE_COLUMN                0x000000004
1736 #endif
1737 
1738 #define dlg_title L"OpenSSL Application SSL Client Certificate Selection"
1739 #define dlg_prompt L"Select a certificate to use for authentication"
1740 #define dlg_columns	 CRYPTUI_SELECT_LOCATION_COLUMN \
1741 			|CRYPTUI_SELECT_INTENDEDUSE_COLUMN
1742 
1743 static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs)
1744 	{
1745 	X509 *x;
1746 	HCERTSTORE dstore;
1747 	PCCERT_CONTEXT cert;
1748 	CAPI_CTX *ctx;
1749 	CAPI_KEY *key;
1750 	HWND hwnd;
1751 	int i, idx = -1;
1752 	if (sk_X509_num(certs) == 1)
1753 		return 0;
1754 	ctx = ENGINE_get_ex_data(e, capi_idx);
1755 	/* Create an in memory store of certificates */
1756 	dstore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1757 					CERT_STORE_CREATE_NEW_FLAG, NULL);
1758 	if (!dstore)
1759 		{
1760 		CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_CREATING_STORE);
1761 		capi_addlasterror();
1762 		goto err;
1763 		}
1764 	/* Add all certificates to store */
1765 	for(i = 0; i < sk_X509_num(certs); i++)
1766 		{
1767 		x = sk_X509_value(certs, i);
1768 		key = X509_get_ex_data(x, cert_capi_idx);
1769 
1770 		if (!CertAddCertificateContextToStore(dstore, key->pcert,
1771 						CERT_STORE_ADD_NEW, NULL))
1772 			{
1773 			CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_ADDING_CERT);
1774 			capi_addlasterror();
1775 			goto err;
1776 			}
1777 
1778 		}
1779 	hwnd = GetForegroundWindow();
1780 	if (!hwnd)
1781 		hwnd = GetActiveWindow();
1782 	if (!hwnd && ctx->getconswindow)
1783 		hwnd = ctx->getconswindow();
1784 	/* Call dialog to select one */
1785 	cert = ctx->certselectdlg(dstore, hwnd, dlg_title, dlg_prompt,
1786 						dlg_columns, 0, NULL);
1787 
1788 	/* Find matching cert from list */
1789 	if (cert)
1790 		{
1791 		for(i = 0; i < sk_X509_num(certs); i++)
1792 			{
1793 			x = sk_X509_value(certs, i);
1794 			key = X509_get_ex_data(x, cert_capi_idx);
1795 			if (CertCompareCertificate(
1796 				X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
1797 					cert->pCertInfo,
1798 					key->pcert->pCertInfo))
1799 				{
1800 				idx = i;
1801 				break;
1802 				}
1803 			}
1804 		}
1805 
1806 	err:
1807 	if (dstore)
1808 		CertCloseStore(dstore, 0);
1809 	return idx;
1810 
1811 	}
1812 #endif
1813 
1814 #else /* !__COMPILE_CAPIENG */
1815 #include <openssl/engine.h>
1816 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
1817 OPENSSL_EXPORT
1818 int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns);
1819 OPENSSL_EXPORT
1820 int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) { return 0; }
1821 IMPLEMENT_DYNAMIC_CHECK_FN()
1822 #else
1823 void ENGINE_load_capi(void){}
1824 #endif
1825 #endif
1826