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