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