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