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