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