Rerun util/openssl-format-source -v -c .
[openssl.git] / engines / e_capi.c
1 /* engines/e_capi.c */
2 /*
3  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4  * project.
5  */
6 /* ====================================================================
7  * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in
18  *    the documentation and/or other materials provided with the
19  *    distribution.
20  *
21  * 3. All advertising materials mentioning features or use of this
22  *    software must display the following acknowledgment:
23  *    "This product includes software developed by the OpenSSL Project
24  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25  *
26  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27  *    endorse or promote products derived from this software without
28  *    prior written permission. For written permission, please contact
29  *    licensing@OpenSSL.org.
30  *
31  * 5. Products derived from this software may not be called "OpenSSL"
32  *    nor may "OpenSSL" appear in their names without prior written
33  *    permission of the OpenSSL Project.
34  *
35  * 6. Redistributions of any form whatsoever must retain the following
36  *    acknowledgment:
37  *    "This product includes software developed by the OpenSSL Project
38  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51  * OF THE POSSIBILITY OF SUCH DAMAGE.
52  * ====================================================================
53  */
54
55 #include <stdio.h>
56 #include <string.h>
57 #include <stdlib.h>
58
59 #include <openssl/crypto.h>
60
61 #ifdef OPENSSL_SYS_WIN32
62 # ifndef OPENSSL_NO_CAPIENG
63
64 #  include <openssl/buffer.h>
65 #  include <openssl/bn.h>
66 #  include <openssl/rsa.h>
67
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
124 static const char *engine_capi_id = "capi";
125 static const char *engine_capi_name = "CryptoAPI ENGINE";
126
127 typedef struct CAPI_CTX_st CAPI_CTX;
128 typedef struct CAPI_KEY_st CAPI_KEY;
129
130 static void capi_addlasterror(void);
131 static void capi_adderror(DWORD err);
132
133 static void CAPI_trace(CAPI_CTX * ctx, char *format, ...);
134
135 static int capi_list_providers(CAPI_CTX * ctx, BIO *out);
136 static int capi_list_containers(CAPI_CTX * ctx, BIO *out);
137 int capi_list_certs(CAPI_CTX * ctx, BIO *out, char *storename);
138 void capi_free_key(CAPI_KEY * key);
139
140 static PCCERT_CONTEXT capi_find_cert(CAPI_CTX * ctx, const char *id,
141                                      HCERTSTORE hstore);
142
143 CAPI_KEY *capi_find_key(CAPI_CTX * ctx, const char *id);
144
145 static EVP_PKEY *capi_load_privkey(ENGINE *eng, const char *key_id,
146                                    UI_METHOD *ui_method, void *callback_data);
147 static 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);
150 static int capi_rsa_priv_enc(int flen, const unsigned char *from,
151                              unsigned char *to, RSA *rsa, int padding);
152 static int capi_rsa_priv_dec(int flen, const unsigned char *from,
153                              unsigned char *to, RSA *rsa, int padding);
154 static int capi_rsa_free(RSA *rsa);
155
156 static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen,
157                                  DSA *dsa);
158 static int capi_dsa_free(DSA *dsa);
159
160 static 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
166 static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
167 # ifdef OPENSSL_CAPIENG_DIALOG
168 static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
169 # endif
170
171 typedef PCCERT_CONTEXT(WINAPI *CERTDLG) (HCERTSTORE, HWND, LPCWSTR,
172                                          LPCWSTR, DWORD, DWORD, void *);
173 typedef 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
183 struct 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
222 static CAPI_CTX *capi_ctx_new();
223 static void capi_ctx_free(CAPI_CTX * ctx);
224 static int capi_ctx_set_provname(CAPI_CTX * ctx, LPSTR pname, DWORD type,
225                                  int check);
226 static 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
243 static 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
305 static int capi_idx = -1;
306 static int rsa_capi_idx = -1;
307 static int dsa_capi_idx = -1;
308 static int cert_capi_idx = -1;
309
310 static 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
405 static 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
421 static 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
436 static 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
496 static int capi_destroy(ENGINE *e)
497 {
498     ERR_unload_CAPI_strings();
499     return 1;
500 }
501
502 static 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
517 struct CAPI_KEY_st {
518     /* Associated certificate context (if any) */
519     PCCERT_CONTEXT pcert;
520     HCRYPTPROV hprov;
521     HCRYPTKEY key;
522     DWORD keyspec;
523 };
524
525 static 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
548 static 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
557 IMPLEMENT_DYNAMIC_CHECK_FN()
558     IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
559 # else
560 static 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
572 void 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
584 static 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
606 static 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
746 static 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
774 int 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
781 int 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
864 int 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
911 static 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
922 static 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
992 static 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
1001 static 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
1013 static 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
1021 static void capi_addlasterror(void)
1022 {
1023     capi_adderror(GetLastError());
1024 }
1025
1026 static 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
1033 static 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
1059 static 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
1095 static 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
1114 static 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
1198 CRYPT_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
1222 static 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
1247 char *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
1270 void 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
1312 HCERTSTORE 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
1331 int 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
1369 static 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
1401 static 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
1444 static 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
1475 CAPI_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
1524 void 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
1537 static 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
1560 static 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
1576 static 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
1609 static 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
1621 static 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
1636 static 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
1740 static 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
1767 static 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
1834 OPENSSL_EXPORT
1835     int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns);
1836 OPENSSL_EXPORT
1837     int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns)
1838 {
1839     return 0;
1840 }
1841
1842 IMPLEMENT_DYNAMIC_CHECK_FN()
1843 # else
1844 void ENGINE_load_capi(void)
1845 {
1846 }
1847 # endif
1848 #endif