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