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