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