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