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