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