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