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