e_capi.c revision 183234
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
94static const char *engine_capi_id = "capi";
95static const char *engine_capi_name = "CryptoAPI ENGINE";
96
97typedef struct CAPI_CTX_st CAPI_CTX;
98typedef struct CAPI_KEY_st CAPI_KEY;
99
100static void capi_addlasterror(void);
101static void capi_adderror(DWORD err);
102
103static void CAPI_trace(CAPI_CTX *ctx, char *format, ...);
104
105static int capi_list_providers(CAPI_CTX *ctx, BIO *out);
106static int capi_list_containers(CAPI_CTX *ctx, BIO *out);
107int capi_list_certs(CAPI_CTX *ctx, BIO *out, char *storename);
108void capi_free_key(CAPI_KEY *key);
109
110static PCCERT_CONTEXT capi_find_cert(CAPI_CTX *ctx, const char *id, HCERTSTORE hstore);
111
112CAPI_KEY *capi_find_key(CAPI_CTX *ctx, const char *id);
113
114static EVP_PKEY *capi_load_privkey(ENGINE *eng, const char *key_id,
115	UI_METHOD *ui_method, void *callback_data);
116static int capi_rsa_sign(int dtype, const unsigned char *m, unsigned int m_len,
117             unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
118static int capi_rsa_priv_enc(int flen, const unsigned char *from,
119                unsigned char *to, RSA *rsa, int padding);
120static int capi_rsa_priv_dec(int flen, const unsigned char *from,
121                unsigned char *to, RSA *rsa, int padding);
122static int capi_rsa_free(RSA *rsa);
123
124static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen,
125							DSA *dsa);
126static int capi_dsa_free(DSA *dsa);
127
128static 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
132static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
133#ifdef OPENSSL_CAPIENG_DIALOG
134static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
135#endif
136
137typedef PCCERT_CONTEXT (WINAPI *CERTDLG)(HCERTSTORE, HWND, LPCWSTR,
138						LPCWSTR, DWORD, DWORD,
139						void *);
140typedef 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
150struct 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
193static CAPI_CTX *capi_ctx_new();
194static void capi_ctx_free(CAPI_CTX *ctx);
195static int capi_ctx_set_provname(CAPI_CTX *ctx, LPSTR pname, DWORD type, int check);
196static 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
213static 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
275static int capi_idx = -1;
276static int rsa_capi_idx = -1;
277static int dsa_capi_idx = -1;
278static int cert_capi_idx = -1;
279
280static 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
381static 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
398static 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
414static 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
465static int capi_destroy(ENGINE *e)
466	{
467	ERR_unload_CAPI_strings();
468	return 1;
469	}
470
471static 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
486struct 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
495static 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
517static 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	}
525IMPLEMENT_DYNAMIC_CHECK_FN()
526IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
527#else
528static 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
541void 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
553static 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
575static 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
718memerr:
719	CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_MALLOC_FAILURE);
720	goto err;
721
722	}
723
724static 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
753int 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
760int 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
848err:
849	CryptDestroyHash(hash);
850
851	return ret;
852	}
853
854int 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
906static 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
917static 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
990err:
991	OPENSSL_cleanse(csigbuf, 40);
992	CryptDestroyHash(hash);
993	return ret;
994	}
995
996static 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
1005static 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
1016static 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
1024static void capi_addlasterror(void)
1025	{
1026	capi_adderror(GetLastError());
1027	}
1028
1029static 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
1036static 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
1051static 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
1081static 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
1101static 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
1168CRYPT_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
1191static 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
1214char * 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
1237void 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
1284HCERTSTORE 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
1304int 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
1348static 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
1382static 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
1410static 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
1435CAPI_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
1465void 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
1479static 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
1504static 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
1520static 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
1540static 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
1549static 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
1567static 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
1677static 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
1702static 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
1777OPENSSL_EXPORT
1778int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) { return 0; }
1779IMPLEMENT_DYNAMIC_CHECK_FN()
1780#endif
1781#endif
1782