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