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