xref: /freebsd/crypto/openssl/engines/e_capi.c (revision 7bded2db17780f5b59bc532689d8a9541f06901e)
1db522d3aSSimon L. B. Nielsen /* engines/e_capi.c */
26f9291ceSJung-uk Kim /*
36f9291ceSJung-uk Kim  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4db522d3aSSimon L. B. Nielsen  * project.
5db522d3aSSimon L. B. Nielsen  */
6db522d3aSSimon L. B. Nielsen /* ====================================================================
7db522d3aSSimon L. B. Nielsen  * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
8db522d3aSSimon L. B. Nielsen  *
9db522d3aSSimon L. B. Nielsen  * Redistribution and use in source and binary forms, with or without
10db522d3aSSimon L. B. Nielsen  * modification, are permitted provided that the following conditions
11db522d3aSSimon L. B. Nielsen  * are met:
12db522d3aSSimon L. B. Nielsen  *
13db522d3aSSimon L. B. Nielsen  * 1. Redistributions of source code must retain the above copyright
14db522d3aSSimon L. B. Nielsen  *    notice, this list of conditions and the following disclaimer.
15db522d3aSSimon L. B. Nielsen  *
16db522d3aSSimon L. B. Nielsen  * 2. Redistributions in binary form must reproduce the above copyright
17db522d3aSSimon L. B. Nielsen  *    notice, this list of conditions and the following disclaimer in
18db522d3aSSimon L. B. Nielsen  *    the documentation and/or other materials provided with the
19db522d3aSSimon L. B. Nielsen  *    distribution.
20db522d3aSSimon L. B. Nielsen  *
21db522d3aSSimon L. B. Nielsen  * 3. All advertising materials mentioning features or use of this
22db522d3aSSimon L. B. Nielsen  *    software must display the following acknowledgment:
23db522d3aSSimon L. B. Nielsen  *    "This product includes software developed by the OpenSSL Project
24db522d3aSSimon L. B. Nielsen  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25db522d3aSSimon L. B. Nielsen  *
26db522d3aSSimon L. B. Nielsen  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27db522d3aSSimon L. B. Nielsen  *    endorse or promote products derived from this software without
28db522d3aSSimon L. B. Nielsen  *    prior written permission. For written permission, please contact
29db522d3aSSimon L. B. Nielsen  *    licensing@OpenSSL.org.
30db522d3aSSimon L. B. Nielsen  *
31db522d3aSSimon L. B. Nielsen  * 5. Products derived from this software may not be called "OpenSSL"
32db522d3aSSimon L. B. Nielsen  *    nor may "OpenSSL" appear in their names without prior written
33db522d3aSSimon L. B. Nielsen  *    permission of the OpenSSL Project.
34db522d3aSSimon L. B. Nielsen  *
35db522d3aSSimon L. B. Nielsen  * 6. Redistributions of any form whatsoever must retain the following
36db522d3aSSimon L. B. Nielsen  *    acknowledgment:
37db522d3aSSimon L. B. Nielsen  *    "This product includes software developed by the OpenSSL Project
38db522d3aSSimon L. B. Nielsen  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39db522d3aSSimon L. B. Nielsen  *
40db522d3aSSimon L. B. Nielsen  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41db522d3aSSimon L. B. Nielsen  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42db522d3aSSimon L. B. Nielsen  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43db522d3aSSimon L. B. Nielsen  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44db522d3aSSimon L. B. Nielsen  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45db522d3aSSimon L. B. Nielsen  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46db522d3aSSimon L. B. Nielsen  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47db522d3aSSimon L. B. Nielsen  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48db522d3aSSimon L. B. Nielsen  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49db522d3aSSimon L. B. Nielsen  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50db522d3aSSimon L. B. Nielsen  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51db522d3aSSimon L. B. Nielsen  * OF THE POSSIBILITY OF SUCH DAMAGE.
52db522d3aSSimon L. B. Nielsen  * ====================================================================
53db522d3aSSimon L. B. Nielsen  */
54db522d3aSSimon L. B. Nielsen 
55db522d3aSSimon L. B. Nielsen #include <stdio.h>
56db522d3aSSimon L. B. Nielsen #include <string.h>
57*7bded2dbSJung-uk Kim #include <stdlib.h>
58*7bded2dbSJung-uk Kim 
59db522d3aSSimon L. B. Nielsen #include <openssl/crypto.h>
60db522d3aSSimon L. B. Nielsen 
61db522d3aSSimon L. B. Nielsen #ifdef OPENSSL_SYS_WIN32
62db522d3aSSimon L. B. Nielsen # ifndef OPENSSL_NO_CAPIENG
63db522d3aSSimon L. B. Nielsen 
64*7bded2dbSJung-uk Kim #  include <openssl/buffer.h>
65*7bded2dbSJung-uk Kim #  include <openssl/bn.h>
666a599222SSimon L. B. Nielsen #  include <openssl/rsa.h>
67db522d3aSSimon L. B. Nielsen 
68db522d3aSSimon L. B. Nielsen #  ifndef _WIN32_WINNT
69db522d3aSSimon L. B. Nielsen #   define _WIN32_WINNT 0x0400
70db522d3aSSimon L. B. Nielsen #  endif
71db522d3aSSimon L. B. Nielsen 
72*7bded2dbSJung-uk Kim #  include <windows.h>
73db522d3aSSimon L. B. Nielsen #  include <wincrypt.h>
74*7bded2dbSJung-uk Kim #  include <malloc.h>
75*7bded2dbSJung-uk Kim #  ifndef alloca
76*7bded2dbSJung-uk Kim #   define alloca _alloca
77*7bded2dbSJung-uk Kim #  endif
78db522d3aSSimon L. B. Nielsen 
791f13597dSJung-uk Kim /*
801f13597dSJung-uk Kim  * This module uses several "new" interfaces, among which is
811f13597dSJung-uk Kim  * CertGetCertificateContextProperty. CERT_KEY_PROV_INFO_PROP_ID is
821f13597dSJung-uk Kim  * one of possible values you can pass to function in question. By
831f13597dSJung-uk Kim  * checking if it's defined we can see if wincrypt.h and accompanying
841f13597dSJung-uk Kim  * crypt32.lib are in shape. The native MingW32 headers up to and
851f13597dSJung-uk Kim  * including __W32API_VERSION 3.14 lack of struct DSSPUBKEY and the
861f13597dSJung-uk Kim  * defines CERT_STORE_PROV_SYSTEM_A and CERT_STORE_READONLY_FLAG,
871f13597dSJung-uk Kim  * so we check for these too and avoid compiling.
881f13597dSJung-uk Kim  * Yes, it's rather "weak" test and if compilation fails,
891f13597dSJung-uk Kim  * then re-configure with -DOPENSSL_NO_CAPIENG.
901f13597dSJung-uk Kim  */
911f13597dSJung-uk Kim #  if defined(CERT_KEY_PROV_INFO_PROP_ID) && \
921f13597dSJung-uk Kim     defined(CERT_STORE_PROV_SYSTEM_A) && \
931f13597dSJung-uk Kim     defined(CERT_STORE_READONLY_FLAG)
941f13597dSJung-uk Kim #   define __COMPILE_CAPIENG
951f13597dSJung-uk Kim #  endif                        /* CERT_KEY_PROV_INFO_PROP_ID */
961f13597dSJung-uk Kim # endif                         /* OPENSSL_NO_CAPIENG */
971f13597dSJung-uk Kim #endif                          /* OPENSSL_SYS_WIN32 */
981f13597dSJung-uk Kim 
991f13597dSJung-uk Kim #ifdef __COMPILE_CAPIENG
1001f13597dSJung-uk Kim 
101db522d3aSSimon L. B. Nielsen # undef X509_EXTENSIONS
102db522d3aSSimon L. B. Nielsen # undef X509_CERT_PAIR
103db522d3aSSimon L. B. Nielsen 
104db522d3aSSimon L. B. Nielsen /* Definitions which may be missing from earlier version of headers */
105db522d3aSSimon L. B. Nielsen # ifndef CERT_STORE_OPEN_EXISTING_FLAG
106db522d3aSSimon L. B. Nielsen #  define CERT_STORE_OPEN_EXISTING_FLAG                   0x00004000
107db522d3aSSimon L. B. Nielsen # endif
108db522d3aSSimon L. B. Nielsen 
109db522d3aSSimon L. B. Nielsen # ifndef CERT_STORE_CREATE_NEW_FLAG
110db522d3aSSimon L. B. Nielsen #  define CERT_STORE_CREATE_NEW_FLAG                      0x00002000
111db522d3aSSimon L. B. Nielsen # endif
112db522d3aSSimon L. B. Nielsen 
113ab8565e2SSimon L. B. Nielsen # ifndef CERT_SYSTEM_STORE_CURRENT_USER
114ab8565e2SSimon L. B. Nielsen #  define CERT_SYSTEM_STORE_CURRENT_USER                  0x00010000
115ab8565e2SSimon L. B. Nielsen # endif
116ab8565e2SSimon L. B. Nielsen 
117db522d3aSSimon L. B. Nielsen # include <openssl/engine.h>
118db522d3aSSimon L. B. Nielsen # include <openssl/pem.h>
119db522d3aSSimon L. B. Nielsen # include <openssl/x509v3.h>
120db522d3aSSimon L. B. Nielsen 
121db522d3aSSimon L. B. Nielsen # include "e_capi_err.h"
122db522d3aSSimon L. B. Nielsen # include "e_capi_err.c"
123db522d3aSSimon L. B. Nielsen 
124db522d3aSSimon L. B. Nielsen static const char *engine_capi_id = "capi";
125db522d3aSSimon L. B. Nielsen static const char *engine_capi_name = "CryptoAPI ENGINE";
126db522d3aSSimon L. B. Nielsen 
127db522d3aSSimon L. B. Nielsen typedef struct CAPI_CTX_st CAPI_CTX;
128db522d3aSSimon L. B. Nielsen typedef struct CAPI_KEY_st CAPI_KEY;
129db522d3aSSimon L. B. Nielsen 
130db522d3aSSimon L. B. Nielsen static void capi_addlasterror(void);
131db522d3aSSimon L. B. Nielsen static void capi_adderror(DWORD err);
132db522d3aSSimon L. B. Nielsen 
133db522d3aSSimon L. B. Nielsen static void CAPI_trace(CAPI_CTX * ctx, char *format, ...);
134db522d3aSSimon L. B. Nielsen 
135db522d3aSSimon L. B. Nielsen static int capi_list_providers(CAPI_CTX * ctx, BIO *out);
136db522d3aSSimon L. B. Nielsen static int capi_list_containers(CAPI_CTX * ctx, BIO *out);
137db522d3aSSimon L. B. Nielsen int capi_list_certs(CAPI_CTX * ctx, BIO *out, char *storename);
138db522d3aSSimon L. B. Nielsen void capi_free_key(CAPI_KEY * key);
139db522d3aSSimon L. B. Nielsen 
1406f9291ceSJung-uk Kim static PCCERT_CONTEXT capi_find_cert(CAPI_CTX * ctx, const char *id,
1416f9291ceSJung-uk Kim                                      HCERTSTORE hstore);
142db522d3aSSimon L. B. Nielsen 
143db522d3aSSimon L. B. Nielsen CAPI_KEY *capi_find_key(CAPI_CTX * ctx, const char *id);
144db522d3aSSimon L. B. Nielsen 
145db522d3aSSimon L. B. Nielsen static EVP_PKEY *capi_load_privkey(ENGINE *eng, const char *key_id,
146db522d3aSSimon L. B. Nielsen                                    UI_METHOD *ui_method, void *callback_data);
1476f9291ceSJung-uk Kim static int capi_rsa_sign(int dtype, const unsigned char *m,
1486f9291ceSJung-uk Kim                          unsigned int m_len, unsigned char *sigret,
1496f9291ceSJung-uk Kim                          unsigned int *siglen, const RSA *rsa);
150db522d3aSSimon L. B. Nielsen static int capi_rsa_priv_enc(int flen, const unsigned char *from,
151db522d3aSSimon L. B. Nielsen                              unsigned char *to, RSA *rsa, int padding);
152db522d3aSSimon L. B. Nielsen static int capi_rsa_priv_dec(int flen, const unsigned char *from,
153db522d3aSSimon L. B. Nielsen                              unsigned char *to, RSA *rsa, int padding);
154db522d3aSSimon L. B. Nielsen static int capi_rsa_free(RSA *rsa);
155db522d3aSSimon L. B. Nielsen 
156db522d3aSSimon L. B. Nielsen static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen,
157db522d3aSSimon L. B. Nielsen                                  DSA *dsa);
158db522d3aSSimon L. B. Nielsen static int capi_dsa_free(DSA *dsa);
159db522d3aSSimon L. B. Nielsen 
160db522d3aSSimon L. B. Nielsen static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl,
1616f9291ceSJung-uk Kim                                      STACK_OF(X509_NAME) *ca_dn, X509 **pcert,
1626f9291ceSJung-uk Kim                                      EVP_PKEY **pkey, STACK_OF(X509) **pother,
1636f9291ceSJung-uk Kim                                      UI_METHOD *ui_method,
1646f9291ceSJung-uk Kim                                      void *callback_data);
165db522d3aSSimon L. B. Nielsen 
166db522d3aSSimon L. B. Nielsen static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
167db522d3aSSimon L. B. Nielsen # ifdef OPENSSL_CAPIENG_DIALOG
168db522d3aSSimon L. B. Nielsen static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
169db522d3aSSimon L. B. Nielsen # endif
170db522d3aSSimon L. B. Nielsen 
171db522d3aSSimon L. B. Nielsen typedef PCCERT_CONTEXT(WINAPI *CERTDLG) (HCERTSTORE, HWND, LPCWSTR,
1726f9291ceSJung-uk Kim                                          LPCWSTR, DWORD, DWORD, void *);
173db522d3aSSimon L. B. Nielsen typedef HWND(WINAPI *GETCONSWIN) (void);
174db522d3aSSimon L. B. Nielsen 
1756f9291ceSJung-uk Kim /*
1766f9291ceSJung-uk Kim  * This structure contains CAPI ENGINE specific data: it contains various
1776f9291ceSJung-uk Kim  * global options and affects how other functions behave.
178db522d3aSSimon L. B. Nielsen  */
179db522d3aSSimon L. B. Nielsen 
180db522d3aSSimon L. B. Nielsen # define CAPI_DBG_TRACE  2
181db522d3aSSimon L. B. Nielsen # define CAPI_DBG_ERROR  1
182db522d3aSSimon L. B. Nielsen 
183db522d3aSSimon L. B. Nielsen struct CAPI_CTX_st {
184db522d3aSSimon L. B. Nielsen     int debug_level;
185db522d3aSSimon L. B. Nielsen     char *debug_file;
186db522d3aSSimon L. B. Nielsen     /* Parameters to use for container lookup */
187db522d3aSSimon L. B. Nielsen     DWORD keytype;
1886a599222SSimon L. B. Nielsen     LPSTR cspname;
189db522d3aSSimon L. B. Nielsen     DWORD csptype;
190db522d3aSSimon L. B. Nielsen     /* Certificate store name to use */
1916a599222SSimon L. B. Nielsen     LPSTR storename;
1926a599222SSimon L. B. Nielsen     LPSTR ssl_client_store;
193db522d3aSSimon L. B. Nielsen     /* System store flags */
194db522d3aSSimon L. B. Nielsen     DWORD store_flags;
195db522d3aSSimon L. B. Nielsen /* Lookup string meanings in load_private_key */
196db522d3aSSimon L. B. Nielsen /* Substring of subject: uses "storename" */
1976a599222SSimon L. B. Nielsen # define CAPI_LU_SUBSTR          1
198db522d3aSSimon L. B. Nielsen /* Friendly name: uses storename */
1996a599222SSimon L. B. Nielsen # define CAPI_LU_FNAME           2
200db522d3aSSimon L. B. Nielsen /* Container name: uses cspname, keytype */
2016a599222SSimon L. B. Nielsen # define CAPI_LU_CONTNAME        3
202db522d3aSSimon L. B. Nielsen     int lookup_method;
203db522d3aSSimon L. B. Nielsen /* Info to dump with dumpcerts option */
204db522d3aSSimon L. B. Nielsen /* Issuer and serial name strings */
205db522d3aSSimon L. B. Nielsen # define CAPI_DMP_SUMMARY        0x1
206db522d3aSSimon L. B. Nielsen /* Friendly name */
207db522d3aSSimon L. B. Nielsen # define CAPI_DMP_FNAME          0x2
208db522d3aSSimon L. B. Nielsen /* Full X509_print dump */
209db522d3aSSimon L. B. Nielsen # define CAPI_DMP_FULL           0x4
210db522d3aSSimon L. B. Nielsen /* Dump PEM format certificate */
211db522d3aSSimon L. B. Nielsen # define CAPI_DMP_PEM            0x8
212db522d3aSSimon L. B. Nielsen /* Dump pseudo key (if possible) */
213db522d3aSSimon L. B. Nielsen # define CAPI_DMP_PSKEY          0x10
214db522d3aSSimon L. B. Nielsen /* Dump key info (if possible) */
215db522d3aSSimon L. B. Nielsen # define CAPI_DMP_PKEYINFO       0x20
216db522d3aSSimon L. B. Nielsen     DWORD dump_flags;
217db522d3aSSimon L. B. Nielsen     int (*client_cert_select) (ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
218db522d3aSSimon L. B. Nielsen     CERTDLG certselectdlg;
219db522d3aSSimon L. B. Nielsen     GETCONSWIN getconswindow;
220db522d3aSSimon L. B. Nielsen };
221db522d3aSSimon L. B. Nielsen 
222db522d3aSSimon L. B. Nielsen static CAPI_CTX *capi_ctx_new();
223db522d3aSSimon L. B. Nielsen static void capi_ctx_free(CAPI_CTX * ctx);
2246f9291ceSJung-uk Kim static int capi_ctx_set_provname(CAPI_CTX * ctx, LPSTR pname, DWORD type,
2256f9291ceSJung-uk Kim                                  int check);
226db522d3aSSimon L. B. Nielsen static int capi_ctx_set_provname_idx(CAPI_CTX * ctx, int idx);
227db522d3aSSimon L. B. Nielsen 
228db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LIST_CERTS             ENGINE_CMD_BASE
229db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LOOKUP_CERT            (ENGINE_CMD_BASE + 1)
230db522d3aSSimon L. B. Nielsen # define CAPI_CMD_DEBUG_LEVEL            (ENGINE_CMD_BASE + 2)
231db522d3aSSimon L. B. Nielsen # define CAPI_CMD_DEBUG_FILE             (ENGINE_CMD_BASE + 3)
232db522d3aSSimon L. B. Nielsen # define CAPI_CMD_KEYTYPE                (ENGINE_CMD_BASE + 4)
233db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LIST_CSPS              (ENGINE_CMD_BASE + 5)
234db522d3aSSimon L. B. Nielsen # define CAPI_CMD_SET_CSP_IDX            (ENGINE_CMD_BASE + 6)
235db522d3aSSimon L. B. Nielsen # define CAPI_CMD_SET_CSP_NAME           (ENGINE_CMD_BASE + 7)
236db522d3aSSimon L. B. Nielsen # define CAPI_CMD_SET_CSP_TYPE           (ENGINE_CMD_BASE + 8)
237db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LIST_CONTAINERS        (ENGINE_CMD_BASE + 9)
238db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LIST_OPTIONS           (ENGINE_CMD_BASE + 10)
239db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LOOKUP_METHOD          (ENGINE_CMD_BASE + 11)
240db522d3aSSimon L. B. Nielsen # define CAPI_CMD_STORE_NAME             (ENGINE_CMD_BASE + 12)
241db522d3aSSimon L. B. Nielsen # define CAPI_CMD_STORE_FLAGS            (ENGINE_CMD_BASE + 13)
242db522d3aSSimon L. B. Nielsen 
243db522d3aSSimon L. B. Nielsen static const ENGINE_CMD_DEFN capi_cmd_defns[] = {
244db522d3aSSimon L. B. Nielsen     {CAPI_CMD_LIST_CERTS,
245db522d3aSSimon L. B. Nielsen      "list_certs",
246db522d3aSSimon L. B. Nielsen      "List all certificates in store",
247db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NO_INPUT},
248db522d3aSSimon L. B. Nielsen     {CAPI_CMD_LOOKUP_CERT,
249db522d3aSSimon L. B. Nielsen      "lookup_cert",
250db522d3aSSimon L. B. Nielsen      "Lookup and output certificates",
251db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_STRING},
252db522d3aSSimon L. B. Nielsen     {CAPI_CMD_DEBUG_LEVEL,
253db522d3aSSimon L. B. Nielsen      "debug_level",
254db522d3aSSimon L. B. Nielsen      "debug level (1=errors, 2=trace)",
255db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NUMERIC},
256db522d3aSSimon L. B. Nielsen     {CAPI_CMD_DEBUG_FILE,
257db522d3aSSimon L. B. Nielsen      "debug_file",
258db522d3aSSimon L. B. Nielsen      "debugging filename)",
259db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_STRING},
260db522d3aSSimon L. B. Nielsen     {CAPI_CMD_KEYTYPE,
261db522d3aSSimon L. B. Nielsen      "key_type",
262db522d3aSSimon L. B. Nielsen      "Key type: 1=AT_KEYEXCHANGE (default), 2=AT_SIGNATURE",
263db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NUMERIC},
264db522d3aSSimon L. B. Nielsen     {CAPI_CMD_LIST_CSPS,
265db522d3aSSimon L. B. Nielsen      "list_csps",
266db522d3aSSimon L. B. Nielsen      "List all CSPs",
267db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NO_INPUT},
268db522d3aSSimon L. B. Nielsen     {CAPI_CMD_SET_CSP_IDX,
269db522d3aSSimon L. B. Nielsen      "csp_idx",
270db522d3aSSimon L. B. Nielsen      "Set CSP by index",
271db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NUMERIC},
272db522d3aSSimon L. B. Nielsen     {CAPI_CMD_SET_CSP_NAME,
273db522d3aSSimon L. B. Nielsen      "csp_name",
274db522d3aSSimon L. B. Nielsen      "Set CSP name, (default CSP used if not specified)",
275db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_STRING},
276db522d3aSSimon L. B. Nielsen     {CAPI_CMD_SET_CSP_TYPE,
277db522d3aSSimon L. B. Nielsen      "csp_type",
278db522d3aSSimon L. B. Nielsen      "Set CSP type, (default RSA_PROV_FULL)",
279db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NUMERIC},
280db522d3aSSimon L. B. Nielsen     {CAPI_CMD_LIST_CONTAINERS,
281db522d3aSSimon L. B. Nielsen      "list_containers",
282db522d3aSSimon L. B. Nielsen      "list container names",
283db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NO_INPUT},
284db522d3aSSimon L. B. Nielsen     {CAPI_CMD_LIST_OPTIONS,
285db522d3aSSimon L. B. Nielsen      "list_options",
286db522d3aSSimon L. B. Nielsen      "Set list options (1=summary,2=friendly name, 4=full printout, 8=PEM output, 16=XXX, "
287db522d3aSSimon L. B. Nielsen      "32=private key info)",
288db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NUMERIC},
289db522d3aSSimon L. B. Nielsen     {CAPI_CMD_LOOKUP_METHOD,
290db522d3aSSimon L. B. Nielsen      "lookup_method",
291db522d3aSSimon L. B. Nielsen      "Set key lookup method (1=substring, 2=friendlyname, 3=container name)",
292db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NUMERIC},
293db522d3aSSimon L. B. Nielsen     {CAPI_CMD_STORE_NAME,
294db522d3aSSimon L. B. Nielsen      "store_name",
295db522d3aSSimon L. B. Nielsen      "certificate store name, default \"MY\"",
296db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_STRING},
297db522d3aSSimon L. B. Nielsen     {CAPI_CMD_STORE_FLAGS,
298db522d3aSSimon L. B. Nielsen      "store_flags",
299db522d3aSSimon L. B. Nielsen      "Certificate store flags: 1 = system store",
300db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NUMERIC},
301db522d3aSSimon L. B. Nielsen 
302db522d3aSSimon L. B. Nielsen     {0, NULL, NULL, 0}
303db522d3aSSimon L. B. Nielsen };
304db522d3aSSimon L. B. Nielsen 
305db522d3aSSimon L. B. Nielsen static int capi_idx = -1;
306db522d3aSSimon L. B. Nielsen static int rsa_capi_idx = -1;
307db522d3aSSimon L. B. Nielsen static int dsa_capi_idx = -1;
308db522d3aSSimon L. B. Nielsen static int cert_capi_idx = -1;
309db522d3aSSimon L. B. Nielsen 
310db522d3aSSimon L. B. Nielsen static int capi_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
311db522d3aSSimon L. B. Nielsen {
312db522d3aSSimon L. B. Nielsen     int ret = 1;
313db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
314db522d3aSSimon L. B. Nielsen     BIO *out;
3156f9291ceSJung-uk Kim     if (capi_idx == -1) {
316db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_ENGINE_NOT_INITIALIZED);
317db522d3aSSimon L. B. Nielsen         return 0;
318db522d3aSSimon L. B. Nielsen     }
319db522d3aSSimon L. B. Nielsen     ctx = ENGINE_get_ex_data(e, capi_idx);
320db522d3aSSimon L. B. Nielsen     out = BIO_new_fp(stdout, BIO_NOCLOSE);
3216f9291ceSJung-uk Kim     switch (cmd) {
322db522d3aSSimon L. B. Nielsen     case CAPI_CMD_LIST_CSPS:
323db522d3aSSimon L. B. Nielsen         ret = capi_list_providers(ctx, out);
324db522d3aSSimon L. B. Nielsen         break;
325db522d3aSSimon L. B. Nielsen 
326db522d3aSSimon L. B. Nielsen     case CAPI_CMD_LIST_CERTS:
327db522d3aSSimon L. B. Nielsen         ret = capi_list_certs(ctx, out, NULL);
328db522d3aSSimon L. B. Nielsen         break;
329db522d3aSSimon L. B. Nielsen 
330db522d3aSSimon L. B. Nielsen     case CAPI_CMD_LOOKUP_CERT:
331db522d3aSSimon L. B. Nielsen         ret = capi_list_certs(ctx, out, p);
332db522d3aSSimon L. B. Nielsen         break;
333db522d3aSSimon L. B. Nielsen 
334db522d3aSSimon L. B. Nielsen     case CAPI_CMD_LIST_CONTAINERS:
335db522d3aSSimon L. B. Nielsen         ret = capi_list_containers(ctx, out);
336db522d3aSSimon L. B. Nielsen         break;
337db522d3aSSimon L. B. Nielsen 
338db522d3aSSimon L. B. Nielsen     case CAPI_CMD_STORE_NAME:
339db522d3aSSimon L. B. Nielsen         if (ctx->storename)
340db522d3aSSimon L. B. Nielsen             OPENSSL_free(ctx->storename);
341db522d3aSSimon L. B. Nielsen         ctx->storename = BUF_strdup(p);
342db522d3aSSimon L. B. Nielsen         CAPI_trace(ctx, "Setting store name to %s\n", p);
343db522d3aSSimon L. B. Nielsen         break;
344db522d3aSSimon L. B. Nielsen 
345db522d3aSSimon L. B. Nielsen     case CAPI_CMD_STORE_FLAGS:
3466f9291ceSJung-uk Kim         if (i & 1) {
347db522d3aSSimon L. B. Nielsen             ctx->store_flags |= CERT_SYSTEM_STORE_LOCAL_MACHINE;
348db522d3aSSimon L. B. Nielsen             ctx->store_flags &= ~CERT_SYSTEM_STORE_CURRENT_USER;
3496f9291ceSJung-uk Kim         } else {
350db522d3aSSimon L. B. Nielsen             ctx->store_flags |= CERT_SYSTEM_STORE_CURRENT_USER;
351db522d3aSSimon L. B. Nielsen             ctx->store_flags &= ~CERT_SYSTEM_STORE_LOCAL_MACHINE;
352db522d3aSSimon L. B. Nielsen         }
353db522d3aSSimon L. B. Nielsen         CAPI_trace(ctx, "Setting flags to %d\n", i);
354db522d3aSSimon L. B. Nielsen         break;
355db522d3aSSimon L. B. Nielsen 
356db522d3aSSimon L. B. Nielsen     case CAPI_CMD_DEBUG_LEVEL:
357db522d3aSSimon L. B. Nielsen         ctx->debug_level = (int)i;
358db522d3aSSimon L. B. Nielsen         CAPI_trace(ctx, "Setting debug level to %d\n", ctx->debug_level);
359db522d3aSSimon L. B. Nielsen         break;
360db522d3aSSimon L. B. Nielsen 
361db522d3aSSimon L. B. Nielsen     case CAPI_CMD_DEBUG_FILE:
362db522d3aSSimon L. B. Nielsen         ctx->debug_file = BUF_strdup(p);
363db522d3aSSimon L. B. Nielsen         CAPI_trace(ctx, "Setting debug file to %s\n", ctx->debug_file);
364db522d3aSSimon L. B. Nielsen         break;
365db522d3aSSimon L. B. Nielsen 
366db522d3aSSimon L. B. Nielsen     case CAPI_CMD_KEYTYPE:
367db522d3aSSimon L. B. Nielsen         ctx->keytype = i;
368db522d3aSSimon L. B. Nielsen         CAPI_trace(ctx, "Setting key type to %d\n", ctx->keytype);
369db522d3aSSimon L. B. Nielsen         break;
370db522d3aSSimon L. B. Nielsen 
371db522d3aSSimon L. B. Nielsen     case CAPI_CMD_SET_CSP_IDX:
372db522d3aSSimon L. B. Nielsen         ret = capi_ctx_set_provname_idx(ctx, i);
373db522d3aSSimon L. B. Nielsen         break;
374db522d3aSSimon L. B. Nielsen 
375db522d3aSSimon L. B. Nielsen     case CAPI_CMD_LIST_OPTIONS:
376db522d3aSSimon L. B. Nielsen         ctx->dump_flags = i;
377db522d3aSSimon L. B. Nielsen         break;
378db522d3aSSimon L. B. Nielsen 
379db522d3aSSimon L. B. Nielsen     case CAPI_CMD_LOOKUP_METHOD:
3806f9291ceSJung-uk Kim         if (i < 1 || i > 3) {
381db522d3aSSimon L. B. Nielsen             CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_INVALID_LOOKUP_METHOD);
382db522d3aSSimon L. B. Nielsen             return 0;
383db522d3aSSimon L. B. Nielsen         }
384db522d3aSSimon L. B. Nielsen         ctx->lookup_method = i;
385db522d3aSSimon L. B. Nielsen         break;
386db522d3aSSimon L. B. Nielsen 
387db522d3aSSimon L. B. Nielsen     case CAPI_CMD_SET_CSP_NAME:
388db522d3aSSimon L. B. Nielsen         ret = capi_ctx_set_provname(ctx, p, ctx->csptype, 1);
389db522d3aSSimon L. B. Nielsen         break;
390db522d3aSSimon L. B. Nielsen 
391db522d3aSSimon L. B. Nielsen     case CAPI_CMD_SET_CSP_TYPE:
392db522d3aSSimon L. B. Nielsen         ctx->csptype = i;
393db522d3aSSimon L. B. Nielsen         break;
394db522d3aSSimon L. B. Nielsen 
395db522d3aSSimon L. B. Nielsen     default:
396db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_UNKNOWN_COMMAND);
397db522d3aSSimon L. B. Nielsen         ret = 0;
398db522d3aSSimon L. B. Nielsen     }
399db522d3aSSimon L. B. Nielsen 
400db522d3aSSimon L. B. Nielsen     BIO_free(out);
401db522d3aSSimon L. B. Nielsen     return ret;
402db522d3aSSimon L. B. Nielsen 
403db522d3aSSimon L. B. Nielsen }
404db522d3aSSimon L. B. Nielsen 
4056f9291ceSJung-uk Kim static RSA_METHOD capi_rsa_method = {
406db522d3aSSimon L. B. Nielsen     "CryptoAPI RSA method",
407db522d3aSSimon L. B. Nielsen     0,                          /* pub_enc */
408db522d3aSSimon L. B. Nielsen     0,                          /* pub_dec */
409db522d3aSSimon L. B. Nielsen     capi_rsa_priv_enc,          /* priv_enc */
410db522d3aSSimon L. B. Nielsen     capi_rsa_priv_dec,          /* priv_dec */
411db522d3aSSimon L. B. Nielsen     0,                          /* rsa_mod_exp */
412db522d3aSSimon L. B. Nielsen     0,                          /* bn_mod_exp */
413db522d3aSSimon L. B. Nielsen     0,                          /* init */
414db522d3aSSimon L. B. Nielsen     capi_rsa_free,              /* finish */
415db522d3aSSimon L. B. Nielsen     RSA_FLAG_SIGN_VER,          /* flags */
416db522d3aSSimon L. B. Nielsen     NULL,                       /* app_data */
417db522d3aSSimon L. B. Nielsen     capi_rsa_sign,              /* rsa_sign */
418db522d3aSSimon L. B. Nielsen     0                           /* rsa_verify */
419db522d3aSSimon L. B. Nielsen };
420db522d3aSSimon L. B. Nielsen 
4216f9291ceSJung-uk Kim static DSA_METHOD capi_dsa_method = {
422db522d3aSSimon L. B. Nielsen     "CryptoAPI DSA method",
423db522d3aSSimon L. B. Nielsen     capi_dsa_do_sign,           /* dsa_do_sign */
424db522d3aSSimon L. B. Nielsen     0,                          /* dsa_sign_setup */
425db522d3aSSimon L. B. Nielsen     0,                          /* dsa_do_verify */
426db522d3aSSimon L. B. Nielsen     0,                          /* dsa_mod_exp */
427db522d3aSSimon L. B. Nielsen     0,                          /* bn_mod_exp */
428db522d3aSSimon L. B. Nielsen     0,                          /* init */
429db522d3aSSimon L. B. Nielsen     capi_dsa_free,              /* finish */
430db522d3aSSimon L. B. Nielsen     0,                          /* flags */
431db522d3aSSimon L. B. Nielsen     NULL,                       /* app_data */
432db522d3aSSimon L. B. Nielsen     0,                          /* dsa_paramgen */
433db522d3aSSimon L. B. Nielsen     0                           /* dsa_keygen */
434db522d3aSSimon L. B. Nielsen };
435db522d3aSSimon L. B. Nielsen 
436db522d3aSSimon L. B. Nielsen static int capi_init(ENGINE *e)
437db522d3aSSimon L. B. Nielsen {
438db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
439db522d3aSSimon L. B. Nielsen     const RSA_METHOD *ossl_rsa_meth;
440db522d3aSSimon L. B. Nielsen     const DSA_METHOD *ossl_dsa_meth;
441db522d3aSSimon L. B. Nielsen 
4426f9291ceSJung-uk Kim     if (capi_idx < 0) {
44312de4ed2SJung-uk Kim         capi_idx = ENGINE_get_ex_new_index(0, NULL, NULL, NULL, 0);
44412de4ed2SJung-uk Kim         if (capi_idx < 0)
445db522d3aSSimon L. B. Nielsen             goto memerr;
446db522d3aSSimon L. B. Nielsen 
44712de4ed2SJung-uk Kim         cert_capi_idx = X509_get_ex_new_index(0, NULL, NULL, NULL, 0);
44812de4ed2SJung-uk Kim 
449db522d3aSSimon L. B. Nielsen         /* Setup RSA_METHOD */
450db522d3aSSimon L. B. Nielsen         rsa_capi_idx = RSA_get_ex_new_index(0, NULL, NULL, NULL, 0);
451db522d3aSSimon L. B. Nielsen         ossl_rsa_meth = RSA_PKCS1_SSLeay();
452db522d3aSSimon L. B. Nielsen         capi_rsa_method.rsa_pub_enc = ossl_rsa_meth->rsa_pub_enc;
453db522d3aSSimon L. B. Nielsen         capi_rsa_method.rsa_pub_dec = ossl_rsa_meth->rsa_pub_dec;
454db522d3aSSimon L. B. Nielsen         capi_rsa_method.rsa_mod_exp = ossl_rsa_meth->rsa_mod_exp;
455db522d3aSSimon L. B. Nielsen         capi_rsa_method.bn_mod_exp = ossl_rsa_meth->bn_mod_exp;
456db522d3aSSimon L. B. Nielsen 
457db522d3aSSimon L. B. Nielsen         /* Setup DSA Method */
458db522d3aSSimon L. B. Nielsen         dsa_capi_idx = DSA_get_ex_new_index(0, NULL, NULL, NULL, 0);
459db522d3aSSimon L. B. Nielsen         ossl_dsa_meth = DSA_OpenSSL();
460db522d3aSSimon L. B. Nielsen         capi_dsa_method.dsa_do_verify = ossl_dsa_meth->dsa_do_verify;
461db522d3aSSimon L. B. Nielsen         capi_dsa_method.dsa_mod_exp = ossl_dsa_meth->dsa_mod_exp;
462db522d3aSSimon L. B. Nielsen         capi_dsa_method.bn_mod_exp = ossl_dsa_meth->bn_mod_exp;
46312de4ed2SJung-uk Kim     }
46412de4ed2SJung-uk Kim 
46512de4ed2SJung-uk Kim     ctx = capi_ctx_new();
46612de4ed2SJung-uk Kim     if (!ctx)
46712de4ed2SJung-uk Kim         goto memerr;
46812de4ed2SJung-uk Kim 
46912de4ed2SJung-uk Kim     ENGINE_set_ex_data(e, capi_idx, ctx);
470db522d3aSSimon L. B. Nielsen 
471db522d3aSSimon L. B. Nielsen # ifdef OPENSSL_CAPIENG_DIALOG
472db522d3aSSimon L. B. Nielsen     {
473db522d3aSSimon L. B. Nielsen         HMODULE cryptui = LoadLibrary(TEXT("CRYPTUI.DLL"));
4746a599222SSimon L. B. Nielsen         HMODULE kernel = GetModuleHandle(TEXT("KERNEL32.DLL"));
475db522d3aSSimon L. B. Nielsen         if (cryptui)
4766f9291ceSJung-uk Kim             ctx->certselectdlg =
4776f9291ceSJung-uk Kim                 (CERTDLG) GetProcAddress(cryptui,
4786f9291ceSJung-uk Kim                                          "CryptUIDlgSelectCertificateFromStore");
479db522d3aSSimon L. B. Nielsen         if (kernel)
4806f9291ceSJung-uk Kim             ctx->getconswindow =
4816f9291ceSJung-uk Kim                 (GETCONSWIN) GetProcAddress(kernel, "GetConsoleWindow");
482db522d3aSSimon L. B. Nielsen         if (cryptui && !OPENSSL_isservice())
483db522d3aSSimon L. B. Nielsen             ctx->client_cert_select = cert_select_dialog;
484db522d3aSSimon L. B. Nielsen     }
485db522d3aSSimon L. B. Nielsen # endif
486db522d3aSSimon L. B. Nielsen 
487db522d3aSSimon L. B. Nielsen     return 1;
488db522d3aSSimon L. B. Nielsen 
489db522d3aSSimon L. B. Nielsen  memerr:
490db522d3aSSimon L. B. Nielsen     CAPIerr(CAPI_F_CAPI_INIT, ERR_R_MALLOC_FAILURE);
491db522d3aSSimon L. B. Nielsen     return 0;
492db522d3aSSimon L. B. Nielsen 
493db522d3aSSimon L. B. Nielsen     return 1;
494db522d3aSSimon L. B. Nielsen }
495db522d3aSSimon L. B. Nielsen 
496db522d3aSSimon L. B. Nielsen static int capi_destroy(ENGINE *e)
497db522d3aSSimon L. B. Nielsen {
498db522d3aSSimon L. B. Nielsen     ERR_unload_CAPI_strings();
499db522d3aSSimon L. B. Nielsen     return 1;
500db522d3aSSimon L. B. Nielsen }
501db522d3aSSimon L. B. Nielsen 
502db522d3aSSimon L. B. Nielsen static int capi_finish(ENGINE *e)
503db522d3aSSimon L. B. Nielsen {
504db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
505db522d3aSSimon L. B. Nielsen     ctx = ENGINE_get_ex_data(e, capi_idx);
506db522d3aSSimon L. B. Nielsen     capi_ctx_free(ctx);
507db522d3aSSimon L. B. Nielsen     ENGINE_set_ex_data(e, capi_idx, NULL);
508db522d3aSSimon L. B. Nielsen     return 1;
509db522d3aSSimon L. B. Nielsen }
510db522d3aSSimon L. B. Nielsen 
5116f9291ceSJung-uk Kim /*
5126f9291ceSJung-uk Kim  * CryptoAPI key application data. This contains a handle to the private key
5136f9291ceSJung-uk Kim  * container (for sign operations) and a handle to the key (for decrypt
5146f9291ceSJung-uk Kim  * operations).
515db522d3aSSimon L. B. Nielsen  */
516db522d3aSSimon L. B. Nielsen 
5176f9291ceSJung-uk Kim struct CAPI_KEY_st {
518db522d3aSSimon L. B. Nielsen     /* Associated certificate context (if any) */
519db522d3aSSimon L. B. Nielsen     PCCERT_CONTEXT pcert;
520db522d3aSSimon L. B. Nielsen     HCRYPTPROV hprov;
521db522d3aSSimon L. B. Nielsen     HCRYPTKEY key;
522db522d3aSSimon L. B. Nielsen     DWORD keyspec;
523db522d3aSSimon L. B. Nielsen };
524db522d3aSSimon L. B. Nielsen 
525db522d3aSSimon L. B. Nielsen static int bind_capi(ENGINE *e)
526db522d3aSSimon L. B. Nielsen {
527db522d3aSSimon L. B. Nielsen     if (!ENGINE_set_id(e, engine_capi_id)
528db522d3aSSimon L. B. Nielsen         || !ENGINE_set_name(e, engine_capi_name)
5291f13597dSJung-uk Kim         || !ENGINE_set_flags(e, ENGINE_FLAGS_NO_REGISTER_ALL)
530db522d3aSSimon L. B. Nielsen         || !ENGINE_set_init_function(e, capi_init)
531db522d3aSSimon L. B. Nielsen         || !ENGINE_set_finish_function(e, capi_finish)
532db522d3aSSimon L. B. Nielsen         || !ENGINE_set_destroy_function(e, capi_destroy)
533db522d3aSSimon L. B. Nielsen         || !ENGINE_set_RSA(e, &capi_rsa_method)
534db522d3aSSimon L. B. Nielsen         || !ENGINE_set_DSA(e, &capi_dsa_method)
535db522d3aSSimon L. B. Nielsen         || !ENGINE_set_load_privkey_function(e, capi_load_privkey)
536db522d3aSSimon L. B. Nielsen         || !ENGINE_set_load_ssl_client_cert_function(e,
537db522d3aSSimon L. B. Nielsen                                                      capi_load_ssl_client_cert)
538db522d3aSSimon L. B. Nielsen         || !ENGINE_set_cmd_defns(e, capi_cmd_defns)
539db522d3aSSimon L. B. Nielsen         || !ENGINE_set_ctrl_function(e, capi_ctrl))
540db522d3aSSimon L. B. Nielsen         return 0;
541db522d3aSSimon L. B. Nielsen     ERR_load_CAPI_strings();
542db522d3aSSimon L. B. Nielsen 
543db522d3aSSimon L. B. Nielsen     return 1;
544db522d3aSSimon L. B. Nielsen 
545db522d3aSSimon L. B. Nielsen }
546db522d3aSSimon L. B. Nielsen 
547db522d3aSSimon L. B. Nielsen # ifndef OPENSSL_NO_DYNAMIC_ENGINE
548db522d3aSSimon L. B. Nielsen static int bind_helper(ENGINE *e, const char *id)
549db522d3aSSimon L. B. Nielsen {
550db522d3aSSimon L. B. Nielsen     if (id && (strcmp(id, engine_capi_id) != 0))
551db522d3aSSimon L. B. Nielsen         return 0;
552db522d3aSSimon L. B. Nielsen     if (!bind_capi(e))
553db522d3aSSimon L. B. Nielsen         return 0;
554db522d3aSSimon L. B. Nielsen     return 1;
555db522d3aSSimon L. B. Nielsen }
5566f9291ceSJung-uk Kim 
557db522d3aSSimon L. B. Nielsen IMPLEMENT_DYNAMIC_CHECK_FN()
558db522d3aSSimon L. B. Nielsen     IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
559db522d3aSSimon L. B. Nielsen # else
560db522d3aSSimon L. B. Nielsen static ENGINE *engine_capi(void)
561db522d3aSSimon L. B. Nielsen {
562db522d3aSSimon L. B. Nielsen     ENGINE *ret = ENGINE_new();
563db522d3aSSimon L. B. Nielsen     if (!ret)
564db522d3aSSimon L. B. Nielsen         return NULL;
5656f9291ceSJung-uk Kim     if (!bind_capi(ret)) {
566db522d3aSSimon L. B. Nielsen         ENGINE_free(ret);
567db522d3aSSimon L. B. Nielsen         return NULL;
568db522d3aSSimon L. B. Nielsen     }
569db522d3aSSimon L. B. Nielsen     return ret;
570db522d3aSSimon L. B. Nielsen }
571db522d3aSSimon L. B. Nielsen 
572db522d3aSSimon L. B. Nielsen void ENGINE_load_capi(void)
573db522d3aSSimon L. B. Nielsen {
574db522d3aSSimon L. B. Nielsen     /* Copied from eng_[openssl|dyn].c */
575db522d3aSSimon L. B. Nielsen     ENGINE *toadd = engine_capi();
5766f9291ceSJung-uk Kim     if (!toadd)
5776f9291ceSJung-uk Kim         return;
578db522d3aSSimon L. B. Nielsen     ENGINE_add(toadd);
579db522d3aSSimon L. B. Nielsen     ENGINE_free(toadd);
580db522d3aSSimon L. B. Nielsen     ERR_clear_error();
581db522d3aSSimon L. B. Nielsen }
582db522d3aSSimon L. B. Nielsen # endif
583db522d3aSSimon L. B. Nielsen 
584db522d3aSSimon L. B. Nielsen static int lend_tobn(BIGNUM *bn, unsigned char *bin, int binlen)
585db522d3aSSimon L. B. Nielsen {
586db522d3aSSimon L. B. Nielsen     int i;
5876f9291ceSJung-uk Kim     /*
5886f9291ceSJung-uk Kim      * Reverse buffer in place: since this is a keyblob structure that will
5896f9291ceSJung-uk Kim      * be freed up after conversion anyway it doesn't matter if we change
5906f9291ceSJung-uk Kim      * it.
591db522d3aSSimon L. B. Nielsen      */
5926f9291ceSJung-uk Kim     for (i = 0; i < binlen / 2; i++) {
593db522d3aSSimon L. B. Nielsen         unsigned char c;
594db522d3aSSimon L. B. Nielsen         c = bin[i];
595db522d3aSSimon L. B. Nielsen         bin[i] = bin[binlen - i - 1];
596db522d3aSSimon L. B. Nielsen         bin[binlen - i - 1] = c;
597db522d3aSSimon L. B. Nielsen     }
598db522d3aSSimon L. B. Nielsen 
599db522d3aSSimon L. B. Nielsen     if (!BN_bin2bn(bin, binlen, bn))
600db522d3aSSimon L. B. Nielsen         return 0;
601db522d3aSSimon L. B. Nielsen     return 1;
602db522d3aSSimon L. B. Nielsen }
603db522d3aSSimon L. B. Nielsen 
604db522d3aSSimon L. B. Nielsen /* Given a CAPI_KEY get an EVP_PKEY structure */
605db522d3aSSimon L. B. Nielsen 
606db522d3aSSimon L. B. Nielsen static EVP_PKEY *capi_get_pkey(ENGINE *eng, CAPI_KEY * key)
607db522d3aSSimon L. B. Nielsen {
608db522d3aSSimon L. B. Nielsen     unsigned char *pubkey = NULL;
609db522d3aSSimon L. B. Nielsen     DWORD len;
610db522d3aSSimon L. B. Nielsen     BLOBHEADER *bh;
611db522d3aSSimon L. B. Nielsen     RSA *rkey = NULL;
612db522d3aSSimon L. B. Nielsen     DSA *dkey = NULL;
613db522d3aSSimon L. B. Nielsen     EVP_PKEY *ret = NULL;
6146f9291ceSJung-uk Kim     if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, NULL, &len)) {
615db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_LENGTH_ERROR);
616db522d3aSSimon L. B. Nielsen         capi_addlasterror();
617db522d3aSSimon L. B. Nielsen         return NULL;
618db522d3aSSimon L. B. Nielsen     }
619db522d3aSSimon L. B. Nielsen 
620db522d3aSSimon L. B. Nielsen     pubkey = OPENSSL_malloc(len);
621db522d3aSSimon L. B. Nielsen 
622db522d3aSSimon L. B. Nielsen     if (!pubkey)
623db522d3aSSimon L. B. Nielsen         goto memerr;
624db522d3aSSimon L. B. Nielsen 
6256f9291ceSJung-uk Kim     if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, pubkey, &len)) {
626db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_ERROR);
627db522d3aSSimon L. B. Nielsen         capi_addlasterror();
628db522d3aSSimon L. B. Nielsen         goto err;
629db522d3aSSimon L. B. Nielsen     }
630db522d3aSSimon L. B. Nielsen 
631db522d3aSSimon L. B. Nielsen     bh = (BLOBHEADER *) pubkey;
6326f9291ceSJung-uk Kim     if (bh->bType != PUBLICKEYBLOB) {
633db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_PUBLIC_KEY_BLOB);
634db522d3aSSimon L. B. Nielsen         goto err;
635db522d3aSSimon L. B. Nielsen     }
6366f9291ceSJung-uk Kim     if (bh->aiKeyAlg == CALG_RSA_SIGN || bh->aiKeyAlg == CALG_RSA_KEYX) {
637db522d3aSSimon L. B. Nielsen         RSAPUBKEY *rp;
638db522d3aSSimon L. B. Nielsen         DWORD rsa_modlen;
639db522d3aSSimon L. B. Nielsen         unsigned char *rsa_modulus;
640db522d3aSSimon L. B. Nielsen         rp = (RSAPUBKEY *) (bh + 1);
6416f9291ceSJung-uk Kim         if (rp->magic != 0x31415352) {
642db522d3aSSimon L. B. Nielsen             char magstr[10];
643db522d3aSSimon L. B. Nielsen             BIO_snprintf(magstr, 10, "%lx", rp->magic);
6446f9291ceSJung-uk Kim             CAPIerr(CAPI_F_CAPI_GET_PKEY,
6456f9291ceSJung-uk Kim                     CAPI_R_INVALID_RSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER);
646db522d3aSSimon L. B. Nielsen             ERR_add_error_data(2, "magic=0x", magstr);
647db522d3aSSimon L. B. Nielsen             goto err;
648db522d3aSSimon L. B. Nielsen         }
649db522d3aSSimon L. B. Nielsen         rsa_modulus = (unsigned char *)(rp + 1);
650db522d3aSSimon L. B. Nielsen         rkey = RSA_new_method(eng);
651db522d3aSSimon L. B. Nielsen         if (!rkey)
652db522d3aSSimon L. B. Nielsen             goto memerr;
653db522d3aSSimon L. B. Nielsen 
654db522d3aSSimon L. B. Nielsen         rkey->e = BN_new();
655db522d3aSSimon L. B. Nielsen         rkey->n = BN_new();
656db522d3aSSimon L. B. Nielsen 
657db522d3aSSimon L. B. Nielsen         if (!rkey->e || !rkey->n)
658db522d3aSSimon L. B. Nielsen             goto memerr;
659db522d3aSSimon L. B. Nielsen 
660db522d3aSSimon L. B. Nielsen         if (!BN_set_word(rkey->e, rp->pubexp))
661db522d3aSSimon L. B. Nielsen             goto memerr;
662db522d3aSSimon L. B. Nielsen 
663db522d3aSSimon L. B. Nielsen         rsa_modlen = rp->bitlen / 8;
664db522d3aSSimon L. B. Nielsen         if (!lend_tobn(rkey->n, rsa_modulus, rsa_modlen))
665db522d3aSSimon L. B. Nielsen             goto memerr;
666db522d3aSSimon L. B. Nielsen 
667db522d3aSSimon L. B. Nielsen         RSA_set_ex_data(rkey, rsa_capi_idx, key);
668db522d3aSSimon L. B. Nielsen 
669db522d3aSSimon L. B. Nielsen         if (!(ret = EVP_PKEY_new()))
670db522d3aSSimon L. B. Nielsen             goto memerr;
671db522d3aSSimon L. B. Nielsen 
672db522d3aSSimon L. B. Nielsen         EVP_PKEY_assign_RSA(ret, rkey);
673db522d3aSSimon L. B. Nielsen         rkey = NULL;
674db522d3aSSimon L. B. Nielsen 
6756f9291ceSJung-uk Kim     } else if (bh->aiKeyAlg == CALG_DSS_SIGN) {
676db522d3aSSimon L. B. Nielsen         DSSPUBKEY *dp;
677db522d3aSSimon L. B. Nielsen         DWORD dsa_plen;
678db522d3aSSimon L. B. Nielsen         unsigned char *btmp;
679db522d3aSSimon L. B. Nielsen         dp = (DSSPUBKEY *) (bh + 1);
6806f9291ceSJung-uk Kim         if (dp->magic != 0x31535344) {
681db522d3aSSimon L. B. Nielsen             char magstr[10];
682db522d3aSSimon L. B. Nielsen             BIO_snprintf(magstr, 10, "%lx", dp->magic);
6836f9291ceSJung-uk Kim             CAPIerr(CAPI_F_CAPI_GET_PKEY,
6846f9291ceSJung-uk Kim                     CAPI_R_INVALID_DSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER);
685db522d3aSSimon L. B. Nielsen             ERR_add_error_data(2, "magic=0x", magstr);
686db522d3aSSimon L. B. Nielsen             goto err;
687db522d3aSSimon L. B. Nielsen         }
688db522d3aSSimon L. B. Nielsen         dsa_plen = dp->bitlen / 8;
689db522d3aSSimon L. B. Nielsen         btmp = (unsigned char *)(dp + 1);
690db522d3aSSimon L. B. Nielsen         dkey = DSA_new_method(eng);
691db522d3aSSimon L. B. Nielsen         if (!dkey)
692db522d3aSSimon L. B. Nielsen             goto memerr;
693db522d3aSSimon L. B. Nielsen         dkey->p = BN_new();
694db522d3aSSimon L. B. Nielsen         dkey->q = BN_new();
695db522d3aSSimon L. B. Nielsen         dkey->g = BN_new();
696db522d3aSSimon L. B. Nielsen         dkey->pub_key = BN_new();
697db522d3aSSimon L. B. Nielsen         if (!dkey->p || !dkey->q || !dkey->g || !dkey->pub_key)
698db522d3aSSimon L. B. Nielsen             goto memerr;
699db522d3aSSimon L. B. Nielsen         if (!lend_tobn(dkey->p, btmp, dsa_plen))
700db522d3aSSimon L. B. Nielsen             goto memerr;
701db522d3aSSimon L. B. Nielsen         btmp += dsa_plen;
702db522d3aSSimon L. B. Nielsen         if (!lend_tobn(dkey->q, btmp, 20))
703db522d3aSSimon L. B. Nielsen             goto memerr;
704db522d3aSSimon L. B. Nielsen         btmp += 20;
705db522d3aSSimon L. B. Nielsen         if (!lend_tobn(dkey->g, btmp, dsa_plen))
706db522d3aSSimon L. B. Nielsen             goto memerr;
707db522d3aSSimon L. B. Nielsen         btmp += dsa_plen;
708db522d3aSSimon L. B. Nielsen         if (!lend_tobn(dkey->pub_key, btmp, dsa_plen))
709db522d3aSSimon L. B. Nielsen             goto memerr;
710db522d3aSSimon L. B. Nielsen         btmp += dsa_plen;
711db522d3aSSimon L. B. Nielsen 
712db522d3aSSimon L. B. Nielsen         DSA_set_ex_data(dkey, dsa_capi_idx, key);
713db522d3aSSimon L. B. Nielsen 
714db522d3aSSimon L. B. Nielsen         if (!(ret = EVP_PKEY_new()))
715db522d3aSSimon L. B. Nielsen             goto memerr;
716db522d3aSSimon L. B. Nielsen 
717db522d3aSSimon L. B. Nielsen         EVP_PKEY_assign_DSA(ret, dkey);
718db522d3aSSimon L. B. Nielsen         dkey = NULL;
7196f9291ceSJung-uk Kim     } else {
720db522d3aSSimon L. B. Nielsen         char algstr[10];
721db522d3aSSimon L. B. Nielsen         BIO_snprintf(algstr, 10, "%lx", bh->aiKeyAlg);
7226f9291ceSJung-uk Kim         CAPIerr(CAPI_F_CAPI_GET_PKEY,
7236f9291ceSJung-uk Kim                 CAPI_R_UNSUPPORTED_PUBLIC_KEY_ALGORITHM);
724db522d3aSSimon L. B. Nielsen         ERR_add_error_data(2, "aiKeyAlg=0x", algstr);
725db522d3aSSimon L. B. Nielsen         goto err;
726db522d3aSSimon L. B. Nielsen     }
727db522d3aSSimon L. B. Nielsen 
728db522d3aSSimon L. B. Nielsen  err:
729db522d3aSSimon L. B. Nielsen     if (pubkey)
730db522d3aSSimon L. B. Nielsen         OPENSSL_free(pubkey);
7316f9291ceSJung-uk Kim     if (!ret) {
732db522d3aSSimon L. B. Nielsen         if (rkey)
733db522d3aSSimon L. B. Nielsen             RSA_free(rkey);
734db522d3aSSimon L. B. Nielsen         if (dkey)
735db522d3aSSimon L. B. Nielsen             DSA_free(dkey);
736db522d3aSSimon L. B. Nielsen     }
737db522d3aSSimon L. B. Nielsen 
738db522d3aSSimon L. B. Nielsen     return ret;
739db522d3aSSimon L. B. Nielsen 
740db522d3aSSimon L. B. Nielsen  memerr:
741db522d3aSSimon L. B. Nielsen     CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_MALLOC_FAILURE);
742db522d3aSSimon L. B. Nielsen     goto err;
743db522d3aSSimon L. B. Nielsen 
744db522d3aSSimon L. B. Nielsen }
745db522d3aSSimon L. B. Nielsen 
746db522d3aSSimon L. B. Nielsen static EVP_PKEY *capi_load_privkey(ENGINE *eng, const char *key_id,
747db522d3aSSimon L. B. Nielsen                                    UI_METHOD *ui_method, void *callback_data)
748db522d3aSSimon L. B. Nielsen {
749db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
750db522d3aSSimon L. B. Nielsen     CAPI_KEY *key;
751db522d3aSSimon L. B. Nielsen     EVP_PKEY *ret;
752db522d3aSSimon L. B. Nielsen     ctx = ENGINE_get_ex_data(eng, capi_idx);
753db522d3aSSimon L. B. Nielsen 
7546f9291ceSJung-uk Kim     if (!ctx) {
755db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_LOAD_PRIVKEY, CAPI_R_CANT_FIND_CAPI_CONTEXT);
756db522d3aSSimon L. B. Nielsen         return NULL;
757db522d3aSSimon L. B. Nielsen     }
758db522d3aSSimon L. B. Nielsen 
759db522d3aSSimon L. B. Nielsen     key = capi_find_key(ctx, key_id);
760db522d3aSSimon L. B. Nielsen 
761db522d3aSSimon L. B. Nielsen     if (!key)
762db522d3aSSimon L. B. Nielsen         return NULL;
763db522d3aSSimon L. B. Nielsen 
764db522d3aSSimon L. B. Nielsen     ret = capi_get_pkey(eng, key);
765db522d3aSSimon L. B. Nielsen 
766db522d3aSSimon L. B. Nielsen     if (!ret)
767db522d3aSSimon L. B. Nielsen         capi_free_key(key);
768db522d3aSSimon L. B. Nielsen     return ret;
769db522d3aSSimon L. B. Nielsen 
770db522d3aSSimon L. B. Nielsen }
771db522d3aSSimon L. B. Nielsen 
772db522d3aSSimon L. B. Nielsen /* CryptoAPI RSA operations */
773db522d3aSSimon L. B. Nielsen 
774db522d3aSSimon L. B. Nielsen int capi_rsa_priv_enc(int flen, const unsigned char *from,
775db522d3aSSimon L. B. Nielsen                       unsigned char *to, RSA *rsa, int padding)
776db522d3aSSimon L. B. Nielsen {
777db522d3aSSimon L. B. Nielsen     CAPIerr(CAPI_F_CAPI_RSA_PRIV_ENC, CAPI_R_FUNCTION_NOT_SUPPORTED);
778db522d3aSSimon L. B. Nielsen     return -1;
779db522d3aSSimon L. B. Nielsen }
780db522d3aSSimon L. B. Nielsen 
781db522d3aSSimon L. B. Nielsen int capi_rsa_sign(int dtype, const unsigned char *m, unsigned int m_len,
782db522d3aSSimon L. B. Nielsen                   unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
783db522d3aSSimon L. B. Nielsen {
784db522d3aSSimon L. B. Nielsen     ALG_ID alg;
785db522d3aSSimon L. B. Nielsen     HCRYPTHASH hash;
786db522d3aSSimon L. B. Nielsen     DWORD slen;
787db522d3aSSimon L. B. Nielsen     unsigned int i;
788db522d3aSSimon L. B. Nielsen     int ret = -1;
789db522d3aSSimon L. B. Nielsen     CAPI_KEY *capi_key;
790db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
791db522d3aSSimon L. B. Nielsen 
792db522d3aSSimon L. B. Nielsen     ctx = ENGINE_get_ex_data(rsa->engine, capi_idx);
793db522d3aSSimon L. B. Nielsen 
794db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "Called CAPI_rsa_sign()\n");
795db522d3aSSimon L. B. Nielsen 
796db522d3aSSimon L. B. Nielsen     capi_key = RSA_get_ex_data(rsa, rsa_capi_idx);
7976f9291ceSJung-uk Kim     if (!capi_key) {
798db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_GET_KEY);
799db522d3aSSimon L. B. Nielsen         return -1;
800db522d3aSSimon L. B. Nielsen     }
801db522d3aSSimon L. B. Nielsen /* Convert the signature type to a CryptoAPI algorithm ID */
8026f9291ceSJung-uk Kim     switch (dtype) {
803db522d3aSSimon L. B. Nielsen     case NID_sha1:
804db522d3aSSimon L. B. Nielsen         alg = CALG_SHA1;
805db522d3aSSimon L. B. Nielsen         break;
806db522d3aSSimon L. B. Nielsen 
807db522d3aSSimon L. B. Nielsen     case NID_md5:
808db522d3aSSimon L. B. Nielsen         alg = CALG_MD5;
809db522d3aSSimon L. B. Nielsen         break;
810db522d3aSSimon L. B. Nielsen 
811db522d3aSSimon L. B. Nielsen     case NID_md5_sha1:
812db522d3aSSimon L. B. Nielsen         alg = CALG_SSL3_SHAMD5;
813db522d3aSSimon L. B. Nielsen         break;
814db522d3aSSimon L. B. Nielsen     default:
815db522d3aSSimon L. B. Nielsen         {
816db522d3aSSimon L. B. Nielsen             char algstr[10];
817db522d3aSSimon L. B. Nielsen             BIO_snprintf(algstr, 10, "%lx", dtype);
818db522d3aSSimon L. B. Nielsen             CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_UNSUPPORTED_ALGORITHM_NID);
819db522d3aSSimon L. B. Nielsen             ERR_add_error_data(2, "NID=0x", algstr);
820db522d3aSSimon L. B. Nielsen             return -1;
821db522d3aSSimon L. B. Nielsen         }
822db522d3aSSimon L. B. Nielsen     }
823db522d3aSSimon L. B. Nielsen 
824db522d3aSSimon L. B. Nielsen /* Create the hash object */
8256f9291ceSJung-uk Kim     if (!CryptCreateHash(capi_key->hprov, alg, 0, 0, &hash)) {
826db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT);
827db522d3aSSimon L. B. Nielsen         capi_addlasterror();
828db522d3aSSimon L. B. Nielsen         return -1;
829db522d3aSSimon L. B. Nielsen     }
830db522d3aSSimon L. B. Nielsen /* Set the hash value to the value passed */
831db522d3aSSimon L. B. Nielsen 
8326f9291ceSJung-uk Kim     if (!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)m, 0)) {
833db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_SET_HASH_VALUE);
834db522d3aSSimon L. B. Nielsen         capi_addlasterror();
835db522d3aSSimon L. B. Nielsen         goto err;
836db522d3aSSimon L. B. Nielsen     }
837db522d3aSSimon L. B. Nielsen 
838db522d3aSSimon L. B. Nielsen /* Finally sign it */
839db522d3aSSimon L. B. Nielsen     slen = RSA_size(rsa);
840*7bded2dbSJung-uk Kim     if (!CryptSignHash(hash, capi_key->keyspec, NULL, 0, sigret, &slen)) {
841db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_ERROR_SIGNING_HASH);
842db522d3aSSimon L. B. Nielsen         capi_addlasterror();
843db522d3aSSimon L. B. Nielsen         goto err;
8446f9291ceSJung-uk Kim     } else {
845db522d3aSSimon L. B. Nielsen         ret = 1;
846db522d3aSSimon L. B. Nielsen         /* Inplace byte reversal of signature */
8476f9291ceSJung-uk Kim         for (i = 0; i < slen / 2; i++) {
848db522d3aSSimon L. B. Nielsen             unsigned char c;
849db522d3aSSimon L. B. Nielsen             c = sigret[i];
850db522d3aSSimon L. B. Nielsen             sigret[i] = sigret[slen - i - 1];
851db522d3aSSimon L. B. Nielsen             sigret[slen - i - 1] = c;
852db522d3aSSimon L. B. Nielsen         }
853db522d3aSSimon L. B. Nielsen         *siglen = slen;
854db522d3aSSimon L. B. Nielsen     }
855db522d3aSSimon L. B. Nielsen 
856db522d3aSSimon L. B. Nielsen     /* Now cleanup */
857db522d3aSSimon L. B. Nielsen 
858db522d3aSSimon L. B. Nielsen  err:
859db522d3aSSimon L. B. Nielsen     CryptDestroyHash(hash);
860db522d3aSSimon L. B. Nielsen 
861db522d3aSSimon L. B. Nielsen     return ret;
862db522d3aSSimon L. B. Nielsen }
863db522d3aSSimon L. B. Nielsen 
864db522d3aSSimon L. B. Nielsen int capi_rsa_priv_dec(int flen, const unsigned char *from,
865db522d3aSSimon L. B. Nielsen                       unsigned char *to, RSA *rsa, int padding)
866db522d3aSSimon L. B. Nielsen {
867db522d3aSSimon L. B. Nielsen     int i;
868db522d3aSSimon L. B. Nielsen     unsigned char *tmpbuf;
869db522d3aSSimon L. B. Nielsen     CAPI_KEY *capi_key;
870db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
871db522d3aSSimon L. B. Nielsen     ctx = ENGINE_get_ex_data(rsa->engine, capi_idx);
872db522d3aSSimon L. B. Nielsen 
873db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "Called capi_rsa_priv_dec()\n");
874db522d3aSSimon L. B. Nielsen 
875db522d3aSSimon L. B. Nielsen     capi_key = RSA_get_ex_data(rsa, rsa_capi_idx);
8766f9291ceSJung-uk Kim     if (!capi_key) {
877db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_CANT_GET_KEY);
878db522d3aSSimon L. B. Nielsen         return -1;
879db522d3aSSimon L. B. Nielsen     }
880db522d3aSSimon L. B. Nielsen 
8816f9291ceSJung-uk Kim     if (padding != RSA_PKCS1_PADDING) {
882db522d3aSSimon L. B. Nielsen         char errstr[10];
883db522d3aSSimon L. B. Nielsen         BIO_snprintf(errstr, 10, "%d", padding);
884db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_UNSUPPORTED_PADDING);
885db522d3aSSimon L. B. Nielsen         ERR_add_error_data(2, "padding=", errstr);
886db522d3aSSimon L. B. Nielsen         return -1;
887db522d3aSSimon L. B. Nielsen     }
888db522d3aSSimon L. B. Nielsen 
889db522d3aSSimon L. B. Nielsen     /* Create temp reverse order version of input */
8906f9291ceSJung-uk Kim     if (!(tmpbuf = OPENSSL_malloc(flen))) {
891db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, ERR_R_MALLOC_FAILURE);
892db522d3aSSimon L. B. Nielsen         return -1;
893db522d3aSSimon L. B. Nielsen     }
894db522d3aSSimon L. B. Nielsen     for (i = 0; i < flen; i++)
895db522d3aSSimon L. B. Nielsen         tmpbuf[flen - i - 1] = from[i];
896db522d3aSSimon L. B. Nielsen 
897db522d3aSSimon L. B. Nielsen     /* Finally decrypt it */
8986f9291ceSJung-uk Kim     if (!CryptDecrypt(capi_key->key, 0, TRUE, 0, tmpbuf, &flen)) {
899db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_DECRYPT_ERROR);
900db522d3aSSimon L. B. Nielsen         capi_addlasterror();
901db522d3aSSimon L. B. Nielsen         OPENSSL_free(tmpbuf);
902db522d3aSSimon L. B. Nielsen         return -1;
9036f9291ceSJung-uk Kim     } else
9046f9291ceSJung-uk Kim         memcpy(to, tmpbuf, flen);
905db522d3aSSimon L. B. Nielsen 
906db522d3aSSimon L. B. Nielsen     OPENSSL_free(tmpbuf);
907db522d3aSSimon L. B. Nielsen 
908db522d3aSSimon L. B. Nielsen     return flen;
909db522d3aSSimon L. B. Nielsen }
910db522d3aSSimon L. B. Nielsen 
911db522d3aSSimon L. B. Nielsen static int capi_rsa_free(RSA *rsa)
912db522d3aSSimon L. B. Nielsen {
913db522d3aSSimon L. B. Nielsen     CAPI_KEY *capi_key;
914db522d3aSSimon L. B. Nielsen     capi_key = RSA_get_ex_data(rsa, rsa_capi_idx);
915db522d3aSSimon L. B. Nielsen     capi_free_key(capi_key);
916db522d3aSSimon L. B. Nielsen     RSA_set_ex_data(rsa, rsa_capi_idx, 0);
917db522d3aSSimon L. B. Nielsen     return 1;
918db522d3aSSimon L. B. Nielsen }
919db522d3aSSimon L. B. Nielsen 
920db522d3aSSimon L. B. Nielsen /* CryptoAPI DSA operations */
921db522d3aSSimon L. B. Nielsen 
922db522d3aSSimon L. B. Nielsen static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen,
923db522d3aSSimon L. B. Nielsen                                  DSA *dsa)
924db522d3aSSimon L. B. Nielsen {
925db522d3aSSimon L. B. Nielsen     HCRYPTHASH hash;
926db522d3aSSimon L. B. Nielsen     DWORD slen;
927db522d3aSSimon L. B. Nielsen     DSA_SIG *ret = NULL;
928db522d3aSSimon L. B. Nielsen     CAPI_KEY *capi_key;
929db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
930db522d3aSSimon L. B. Nielsen     unsigned char csigbuf[40];
931db522d3aSSimon L. B. Nielsen 
932db522d3aSSimon L. B. Nielsen     ctx = ENGINE_get_ex_data(dsa->engine, capi_idx);
933db522d3aSSimon L. B. Nielsen 
934db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "Called CAPI_dsa_do_sign()\n");
935db522d3aSSimon L. B. Nielsen 
936db522d3aSSimon L. B. Nielsen     capi_key = DSA_get_ex_data(dsa, dsa_capi_idx);
937db522d3aSSimon L. B. Nielsen 
9386f9291ceSJung-uk Kim     if (!capi_key) {
939db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_GET_KEY);
940db522d3aSSimon L. B. Nielsen         return NULL;
941db522d3aSSimon L. B. Nielsen     }
942db522d3aSSimon L. B. Nielsen 
9436f9291ceSJung-uk Kim     if (dlen != 20) {
944db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_INVALID_DIGEST_LENGTH);
945db522d3aSSimon L. B. Nielsen         return NULL;
946db522d3aSSimon L. B. Nielsen     }
947db522d3aSSimon L. B. Nielsen 
948db522d3aSSimon L. B. Nielsen     /* Create the hash object */
9496f9291ceSJung-uk Kim     if (!CryptCreateHash(capi_key->hprov, CALG_SHA1, 0, 0, &hash)) {
950db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT);
951db522d3aSSimon L. B. Nielsen         capi_addlasterror();
952db522d3aSSimon L. B. Nielsen         return NULL;
953db522d3aSSimon L. B. Nielsen     }
954db522d3aSSimon L. B. Nielsen 
955db522d3aSSimon L. B. Nielsen     /* Set the hash value to the value passed */
9566f9291ceSJung-uk Kim     if (!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)digest, 0)) {
957db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_SET_HASH_VALUE);
958db522d3aSSimon L. B. Nielsen         capi_addlasterror();
959db522d3aSSimon L. B. Nielsen         goto err;
960db522d3aSSimon L. B. Nielsen     }
961db522d3aSSimon L. B. Nielsen 
962db522d3aSSimon L. B. Nielsen     /* Finally sign it */
963db522d3aSSimon L. B. Nielsen     slen = sizeof(csigbuf);
964*7bded2dbSJung-uk Kim     if (!CryptSignHash(hash, capi_key->keyspec, NULL, 0, csigbuf, &slen)) {
965db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_ERROR_SIGNING_HASH);
966db522d3aSSimon L. B. Nielsen         capi_addlasterror();
967db522d3aSSimon L. B. Nielsen         goto err;
9686f9291ceSJung-uk Kim     } else {
969db522d3aSSimon L. B. Nielsen         ret = DSA_SIG_new();
970db522d3aSSimon L. B. Nielsen         if (!ret)
971db522d3aSSimon L. B. Nielsen             goto err;
972db522d3aSSimon L. B. Nielsen         ret->r = BN_new();
973db522d3aSSimon L. B. Nielsen         ret->s = BN_new();
974db522d3aSSimon L. B. Nielsen         if (!ret->r || !ret->s)
975db522d3aSSimon L. B. Nielsen             goto err;
976db522d3aSSimon L. B. Nielsen         if (!lend_tobn(ret->r, csigbuf, 20)
9776f9291ceSJung-uk Kim             || !lend_tobn(ret->s, csigbuf + 20, 20)) {
978db522d3aSSimon L. B. Nielsen             DSA_SIG_free(ret);
979db522d3aSSimon L. B. Nielsen             ret = NULL;
980db522d3aSSimon L. B. Nielsen             goto err;
981db522d3aSSimon L. B. Nielsen         }
982db522d3aSSimon L. B. Nielsen     }
983db522d3aSSimon L. B. Nielsen 
984db522d3aSSimon L. B. Nielsen     /* Now cleanup */
985db522d3aSSimon L. B. Nielsen 
986db522d3aSSimon L. B. Nielsen  err:
987db522d3aSSimon L. B. Nielsen     OPENSSL_cleanse(csigbuf, 40);
988db522d3aSSimon L. B. Nielsen     CryptDestroyHash(hash);
989db522d3aSSimon L. B. Nielsen     return ret;
990db522d3aSSimon L. B. Nielsen }
991db522d3aSSimon L. B. Nielsen 
992db522d3aSSimon L. B. Nielsen static int capi_dsa_free(DSA *dsa)
993db522d3aSSimon L. B. Nielsen {
994db522d3aSSimon L. B. Nielsen     CAPI_KEY *capi_key;
995db522d3aSSimon L. B. Nielsen     capi_key = DSA_get_ex_data(dsa, dsa_capi_idx);
996db522d3aSSimon L. B. Nielsen     capi_free_key(capi_key);
997db522d3aSSimon L. B. Nielsen     DSA_set_ex_data(dsa, dsa_capi_idx, 0);
998db522d3aSSimon L. B. Nielsen     return 1;
999db522d3aSSimon L. B. Nielsen }
1000db522d3aSSimon L. B. Nielsen 
10016f9291ceSJung-uk Kim static void capi_vtrace(CAPI_CTX * ctx, int level, char *format,
10026f9291ceSJung-uk Kim                         va_list argptr)
1003db522d3aSSimon L. B. Nielsen {
1004db522d3aSSimon L. B. Nielsen     BIO *out;
1005db522d3aSSimon L. B. Nielsen 
1006db522d3aSSimon L. B. Nielsen     if (!ctx || (ctx->debug_level < level) || (!ctx->debug_file))
1007db522d3aSSimon L. B. Nielsen         return;
1008db522d3aSSimon L. B. Nielsen     out = BIO_new_file(ctx->debug_file, "a+");
1009db522d3aSSimon L. B. Nielsen     BIO_vprintf(out, format, argptr);
1010db522d3aSSimon L. B. Nielsen     BIO_free(out);
1011db522d3aSSimon L. B. Nielsen }
1012db522d3aSSimon L. B. Nielsen 
1013db522d3aSSimon L. B. Nielsen static void CAPI_trace(CAPI_CTX * ctx, char *format, ...)
1014db522d3aSSimon L. B. Nielsen {
1015db522d3aSSimon L. B. Nielsen     va_list args;
1016db522d3aSSimon L. B. Nielsen     va_start(args, format);
1017db522d3aSSimon L. B. Nielsen     capi_vtrace(ctx, CAPI_DBG_TRACE, format, args);
1018db522d3aSSimon L. B. Nielsen     va_end(args);
1019db522d3aSSimon L. B. Nielsen }
1020db522d3aSSimon L. B. Nielsen 
1021db522d3aSSimon L. B. Nielsen static void capi_addlasterror(void)
1022db522d3aSSimon L. B. Nielsen {
1023db522d3aSSimon L. B. Nielsen     capi_adderror(GetLastError());
1024db522d3aSSimon L. B. Nielsen }
1025db522d3aSSimon L. B. Nielsen 
1026db522d3aSSimon L. B. Nielsen static void capi_adderror(DWORD err)
1027db522d3aSSimon L. B. Nielsen {
1028db522d3aSSimon L. B. Nielsen     char errstr[10];
1029db522d3aSSimon L. B. Nielsen     BIO_snprintf(errstr, 10, "%lX", err);
1030db522d3aSSimon L. B. Nielsen     ERR_add_error_data(2, "Error code= 0x", errstr);
1031db522d3aSSimon L. B. Nielsen }
1032db522d3aSSimon L. B. Nielsen 
1033*7bded2dbSJung-uk Kim static char *wide_to_asc(LPCWSTR wstr)
1034db522d3aSSimon L. B. Nielsen {
1035db522d3aSSimon L. B. Nielsen     char *str;
10366a599222SSimon L. B. Nielsen     int len_0, sz;
10376a599222SSimon L. B. Nielsen 
1038db522d3aSSimon L. B. Nielsen     if (!wstr)
1039db522d3aSSimon L. B. Nielsen         return NULL;
10406a599222SSimon L. B. Nielsen     len_0 = (int)wcslen(wstr) + 1; /* WideCharToMultiByte expects int */
10416a599222SSimon L. B. Nielsen     sz = WideCharToMultiByte(CP_ACP, 0, wstr, len_0, NULL, 0, NULL, NULL);
10426f9291ceSJung-uk Kim     if (!sz) {
10436a599222SSimon L. B. Nielsen         CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_WIN32_ERROR);
10446a599222SSimon L. B. Nielsen         return NULL;
10456a599222SSimon L. B. Nielsen     }
10466a599222SSimon L. B. Nielsen     str = OPENSSL_malloc(sz);
10476f9291ceSJung-uk Kim     if (!str) {
1048db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_WIDE_TO_ASC, ERR_R_MALLOC_FAILURE);
1049db522d3aSSimon L. B. Nielsen         return NULL;
1050db522d3aSSimon L. B. Nielsen     }
10516f9291ceSJung-uk Kim     if (!WideCharToMultiByte(CP_ACP, 0, wstr, len_0, str, sz, NULL, NULL)) {
10526a599222SSimon L. B. Nielsen         OPENSSL_free(str);
10536a599222SSimon L. B. Nielsen         CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_WIN32_ERROR);
10546a599222SSimon L. B. Nielsen         return NULL;
10556a599222SSimon L. B. Nielsen     }
1056db522d3aSSimon L. B. Nielsen     return str;
1057db522d3aSSimon L. B. Nielsen }
1058db522d3aSSimon L. B. Nielsen 
10596f9291ceSJung-uk Kim static int capi_get_provname(CAPI_CTX * ctx, LPSTR * pname, DWORD * ptype,
10606f9291ceSJung-uk Kim                              DWORD idx)
1061db522d3aSSimon L. B. Nielsen {
1062db522d3aSSimon L. B. Nielsen     DWORD len, err;
1063*7bded2dbSJung-uk Kim     LPTSTR name;
1064db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "capi_get_provname, index=%d\n", idx);
1065*7bded2dbSJung-uk Kim     if (!CryptEnumProviders(idx, NULL, 0, ptype, NULL, &len)) {
1066db522d3aSSimon L. B. Nielsen         err = GetLastError();
1067db522d3aSSimon L. B. Nielsen         if (err == ERROR_NO_MORE_ITEMS)
1068db522d3aSSimon L. B. Nielsen             return 2;
1069db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_PROVNAME, CAPI_R_CRYPTENUMPROVIDERS_ERROR);
1070db522d3aSSimon L. B. Nielsen         capi_adderror(err);
1071db522d3aSSimon L. B. Nielsen         return 0;
1072db522d3aSSimon L. B. Nielsen     }
1073*7bded2dbSJung-uk Kim     if (sizeof(TCHAR) != sizeof(char))
1074*7bded2dbSJung-uk Kim         name = alloca(len);
1075*7bded2dbSJung-uk Kim     else
1076db522d3aSSimon L. B. Nielsen         name = OPENSSL_malloc(len);
1077*7bded2dbSJung-uk Kim     if (!CryptEnumProviders(idx, NULL, 0, ptype, name, &len)) {
1078db522d3aSSimon L. B. Nielsen         err = GetLastError();
1079db522d3aSSimon L. B. Nielsen         if (err == ERROR_NO_MORE_ITEMS)
1080db522d3aSSimon L. B. Nielsen             return 2;
1081db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_PROVNAME, CAPI_R_CRYPTENUMPROVIDERS_ERROR);
1082db522d3aSSimon L. B. Nielsen         capi_adderror(err);
1083db522d3aSSimon L. B. Nielsen         return 0;
1084db522d3aSSimon L. B. Nielsen     }
1085*7bded2dbSJung-uk Kim     if (sizeof(TCHAR) != sizeof(char))
1086*7bded2dbSJung-uk Kim         *pname = wide_to_asc((WCHAR *)name);
1087*7bded2dbSJung-uk Kim     else
1088*7bded2dbSJung-uk Kim         *pname = (char *)name;
1089*7bded2dbSJung-uk Kim     CAPI_trace(ctx, "capi_get_provname, returned name=%s, type=%d\n", *pname,
10906f9291ceSJung-uk Kim                *ptype);
1091db522d3aSSimon L. B. Nielsen 
1092db522d3aSSimon L. B. Nielsen     return 1;
1093db522d3aSSimon L. B. Nielsen }
1094db522d3aSSimon L. B. Nielsen 
1095db522d3aSSimon L. B. Nielsen static int capi_list_providers(CAPI_CTX * ctx, BIO *out)
1096db522d3aSSimon L. B. Nielsen {
1097db522d3aSSimon L. B. Nielsen     DWORD idx, ptype;
1098db522d3aSSimon L. B. Nielsen     int ret;
10996a599222SSimon L. B. Nielsen     LPSTR provname = NULL;
1100db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "capi_list_providers\n");
1101db522d3aSSimon L. B. Nielsen     BIO_printf(out, "Available CSPs:\n");
11026f9291ceSJung-uk Kim     for (idx = 0;; idx++) {
1103db522d3aSSimon L. B. Nielsen         ret = capi_get_provname(ctx, &provname, &ptype, idx);
1104db522d3aSSimon L. B. Nielsen         if (ret == 2)
1105db522d3aSSimon L. B. Nielsen             break;
1106db522d3aSSimon L. B. Nielsen         if (ret == 0)
1107db522d3aSSimon L. B. Nielsen             break;
1108db522d3aSSimon L. B. Nielsen         BIO_printf(out, "%d. %s, type %d\n", idx, provname, ptype);
1109db522d3aSSimon L. B. Nielsen         OPENSSL_free(provname);
1110db522d3aSSimon L. B. Nielsen     }
1111db522d3aSSimon L. B. Nielsen     return 1;
1112db522d3aSSimon L. B. Nielsen }
1113db522d3aSSimon L. B. Nielsen 
1114db522d3aSSimon L. B. Nielsen static int capi_list_containers(CAPI_CTX * ctx, BIO *out)
1115db522d3aSSimon L. B. Nielsen {
1116db522d3aSSimon L. B. Nielsen     int ret = 1;
1117db522d3aSSimon L. B. Nielsen     HCRYPTPROV hprov;
1118db522d3aSSimon L. B. Nielsen     DWORD err, idx, flags, buflen = 0, clen;
1119db522d3aSSimon L. B. Nielsen     LPSTR cname;
1120*7bded2dbSJung-uk Kim     LPTSTR cspname = NULL;
1121*7bded2dbSJung-uk Kim 
11226f9291ceSJung-uk Kim     CAPI_trace(ctx, "Listing containers CSP=%s, type = %d\n", ctx->cspname,
11236f9291ceSJung-uk Kim                ctx->csptype);
1124*7bded2dbSJung-uk Kim     if (ctx->cspname && sizeof(TCHAR) != sizeof(char)) {
1125*7bded2dbSJung-uk Kim         if ((clen =
1126*7bded2dbSJung-uk Kim              MultiByteToWideChar(CP_ACP, 0, ctx->cspname, -1, NULL, 0))) {
1127*7bded2dbSJung-uk Kim             cspname = alloca(clen * sizeof(WCHAR));
1128*7bded2dbSJung-uk Kim             MultiByteToWideChar(CP_ACP, 0, ctx->cspname, -1, (WCHAR *)cspname,
1129*7bded2dbSJung-uk Kim                                 clen);
1130*7bded2dbSJung-uk Kim         }
1131*7bded2dbSJung-uk Kim         if (!cspname) {
1132*7bded2dbSJung-uk Kim             CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, ERR_R_MALLOC_FAILURE);
1133*7bded2dbSJung-uk Kim             capi_addlasterror();
1134*7bded2dbSJung-uk Kim             return 0;
1135*7bded2dbSJung-uk Kim         }
1136*7bded2dbSJung-uk Kim     } else
1137*7bded2dbSJung-uk Kim         cspname = (TCHAR *)ctx->cspname;
1138*7bded2dbSJung-uk Kim     if (!CryptAcquireContext
1139*7bded2dbSJung-uk Kim         (&hprov, NULL, cspname, ctx->csptype, CRYPT_VERIFYCONTEXT)) {
11406f9291ceSJung-uk Kim         CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS,
11416f9291ceSJung-uk Kim                 CAPI_R_CRYPTACQUIRECONTEXT_ERROR);
1142db522d3aSSimon L. B. Nielsen         capi_addlasterror();
1143db522d3aSSimon L. B. Nielsen         return 0;
1144db522d3aSSimon L. B. Nielsen     }
11456f9291ceSJung-uk Kim     if (!CryptGetProvParam
11466f9291ceSJung-uk Kim         (hprov, PP_ENUMCONTAINERS, NULL, &buflen, CRYPT_FIRST)) {
1147db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_ENUMCONTAINERS_ERROR);
1148db522d3aSSimon L. B. Nielsen         capi_addlasterror();
114912de4ed2SJung-uk Kim         CryptReleaseContext(hprov, 0);
1150db522d3aSSimon L. B. Nielsen         return 0;
1151db522d3aSSimon L. B. Nielsen     }
1152db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "Got max container len %d\n", buflen);
1153db522d3aSSimon L. B. Nielsen     if (buflen == 0)
1154db522d3aSSimon L. B. Nielsen         buflen = 1024;
1155db522d3aSSimon L. B. Nielsen     cname = OPENSSL_malloc(buflen);
11566f9291ceSJung-uk Kim     if (!cname) {
1157db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, ERR_R_MALLOC_FAILURE);
1158db522d3aSSimon L. B. Nielsen         goto err;
1159db522d3aSSimon L. B. Nielsen     }
1160db522d3aSSimon L. B. Nielsen 
11616f9291ceSJung-uk Kim     for (idx = 0;; idx++) {
1162db522d3aSSimon L. B. Nielsen         clen = buflen;
1163db522d3aSSimon L. B. Nielsen         cname[0] = 0;
1164db522d3aSSimon L. B. Nielsen 
1165db522d3aSSimon L. B. Nielsen         if (idx == 0)
1166db522d3aSSimon L. B. Nielsen             flags = CRYPT_FIRST;
1167db522d3aSSimon L. B. Nielsen         else
1168db522d3aSSimon L. B. Nielsen             flags = 0;
1169*7bded2dbSJung-uk Kim         if (!CryptGetProvParam
1170*7bded2dbSJung-uk Kim             (hprov, PP_ENUMCONTAINERS, (BYTE *) cname, &clen, flags)) {
1171db522d3aSSimon L. B. Nielsen             err = GetLastError();
1172db522d3aSSimon L. B. Nielsen             if (err == ERROR_NO_MORE_ITEMS)
1173db522d3aSSimon L. B. Nielsen                 goto done;
1174db522d3aSSimon L. B. Nielsen             CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_ENUMCONTAINERS_ERROR);
1175db522d3aSSimon L. B. Nielsen             capi_adderror(err);
1176db522d3aSSimon L. B. Nielsen             goto err;
1177db522d3aSSimon L. B. Nielsen         }
11786f9291ceSJung-uk Kim         CAPI_trace(ctx, "Container name %s, len=%d, index=%d, flags=%d\n",
11796f9291ceSJung-uk Kim                    cname, clen, idx, flags);
11806f9291ceSJung-uk Kim         if (!cname[0] && (clen == buflen)) {
1181db522d3aSSimon L. B. Nielsen             CAPI_trace(ctx, "Enumerate bug: using workaround\n");
1182db522d3aSSimon L. B. Nielsen             goto done;
1183db522d3aSSimon L. B. Nielsen         }
1184db522d3aSSimon L. B. Nielsen         BIO_printf(out, "%d. %s\n", idx, cname);
1185db522d3aSSimon L. B. Nielsen     }
1186db522d3aSSimon L. B. Nielsen  err:
1187db522d3aSSimon L. B. Nielsen 
1188db522d3aSSimon L. B. Nielsen     ret = 0;
1189db522d3aSSimon L. B. Nielsen 
1190db522d3aSSimon L. B. Nielsen  done:
1191db522d3aSSimon L. B. Nielsen     if (cname)
1192db522d3aSSimon L. B. Nielsen         OPENSSL_free(cname);
1193db522d3aSSimon L. B. Nielsen     CryptReleaseContext(hprov, 0);
1194db522d3aSSimon L. B. Nielsen 
1195db522d3aSSimon L. B. Nielsen     return ret;
1196db522d3aSSimon L. B. Nielsen }
1197db522d3aSSimon L. B. Nielsen 
1198db522d3aSSimon L. B. Nielsen CRYPT_KEY_PROV_INFO *capi_get_prov_info(CAPI_CTX * ctx, PCCERT_CONTEXT cert)
1199db522d3aSSimon L. B. Nielsen {
1200db522d3aSSimon L. B. Nielsen     DWORD len;
1201db522d3aSSimon L. B. Nielsen     CRYPT_KEY_PROV_INFO *pinfo;
1202db522d3aSSimon L. B. Nielsen 
12036f9291ceSJung-uk Kim     if (!CertGetCertificateContextProperty
12046f9291ceSJung-uk Kim         (cert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &len))
1205db522d3aSSimon L. B. Nielsen         return NULL;
1206db522d3aSSimon L. B. Nielsen     pinfo = OPENSSL_malloc(len);
12076f9291ceSJung-uk Kim     if (!pinfo) {
1208db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_PROV_INFO, ERR_R_MALLOC_FAILURE);
1209db522d3aSSimon L. B. Nielsen         return NULL;
1210db522d3aSSimon L. B. Nielsen     }
12116f9291ceSJung-uk Kim     if (!CertGetCertificateContextProperty
12126f9291ceSJung-uk Kim         (cert, CERT_KEY_PROV_INFO_PROP_ID, pinfo, &len)) {
12136f9291ceSJung-uk Kim         CAPIerr(CAPI_F_CAPI_GET_PROV_INFO,
12146f9291ceSJung-uk Kim                 CAPI_R_ERROR_GETTING_KEY_PROVIDER_INFO);
1215db522d3aSSimon L. B. Nielsen         capi_addlasterror();
1216db522d3aSSimon L. B. Nielsen         OPENSSL_free(pinfo);
1217db522d3aSSimon L. B. Nielsen         return NULL;
1218db522d3aSSimon L. B. Nielsen     }
1219db522d3aSSimon L. B. Nielsen     return pinfo;
1220db522d3aSSimon L. B. Nielsen }
1221db522d3aSSimon L. B. Nielsen 
12226f9291ceSJung-uk Kim static void capi_dump_prov_info(CAPI_CTX * ctx, BIO *out,
12236f9291ceSJung-uk Kim                                 CRYPT_KEY_PROV_INFO * pinfo)
1224db522d3aSSimon L. B. Nielsen {
1225db522d3aSSimon L. B. Nielsen     char *provname = NULL, *contname = NULL;
12266f9291ceSJung-uk Kim     if (!pinfo) {
1227db522d3aSSimon L. B. Nielsen         BIO_printf(out, "  No Private Key\n");
1228db522d3aSSimon L. B. Nielsen         return;
1229db522d3aSSimon L. B. Nielsen     }
1230db522d3aSSimon L. B. Nielsen     provname = wide_to_asc(pinfo->pwszProvName);
1231db522d3aSSimon L. B. Nielsen     contname = wide_to_asc(pinfo->pwszContainerName);
1232db522d3aSSimon L. B. Nielsen     if (!provname || !contname)
1233db522d3aSSimon L. B. Nielsen         goto err;
1234db522d3aSSimon L. B. Nielsen 
1235db522d3aSSimon L. B. Nielsen     BIO_printf(out, "  Private Key Info:\n");
12366f9291ceSJung-uk Kim     BIO_printf(out, "    Provider Name:  %s, Provider Type %d\n", provname,
12376f9291ceSJung-uk Kim                pinfo->dwProvType);
12386f9291ceSJung-uk Kim     BIO_printf(out, "    Container Name: %s, Key Type %d\n", contname,
12396f9291ceSJung-uk Kim                pinfo->dwKeySpec);
1240db522d3aSSimon L. B. Nielsen  err:
1241db522d3aSSimon L. B. Nielsen     if (provname)
1242db522d3aSSimon L. B. Nielsen         OPENSSL_free(provname);
1243db522d3aSSimon L. B. Nielsen     if (contname)
1244db522d3aSSimon L. B. Nielsen         OPENSSL_free(contname);
1245db522d3aSSimon L. B. Nielsen }
1246db522d3aSSimon L. B. Nielsen 
1247db522d3aSSimon L. B. Nielsen char *capi_cert_get_fname(CAPI_CTX * ctx, PCCERT_CONTEXT cert)
1248db522d3aSSimon L. B. Nielsen {
1249db522d3aSSimon L. B. Nielsen     LPWSTR wfname;
1250db522d3aSSimon L. B. Nielsen     DWORD dlen;
1251db522d3aSSimon L. B. Nielsen 
1252db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "capi_cert_get_fname\n");
12536f9291ceSJung-uk Kim     if (!CertGetCertificateContextProperty
12546f9291ceSJung-uk Kim         (cert, CERT_FRIENDLY_NAME_PROP_ID, NULL, &dlen))
1255db522d3aSSimon L. B. Nielsen         return NULL;
1256db522d3aSSimon L. B. Nielsen     wfname = OPENSSL_malloc(dlen);
12576f9291ceSJung-uk Kim     if (CertGetCertificateContextProperty
12586f9291ceSJung-uk Kim         (cert, CERT_FRIENDLY_NAME_PROP_ID, wfname, &dlen)) {
1259db522d3aSSimon L. B. Nielsen         char *fname = wide_to_asc(wfname);
1260db522d3aSSimon L. B. Nielsen         OPENSSL_free(wfname);
1261db522d3aSSimon L. B. Nielsen         return fname;
1262db522d3aSSimon L. B. Nielsen     }
1263db522d3aSSimon L. B. Nielsen     CAPIerr(CAPI_F_CAPI_CERT_GET_FNAME, CAPI_R_ERROR_GETTING_FRIENDLY_NAME);
1264db522d3aSSimon L. B. Nielsen     capi_addlasterror();
1265db522d3aSSimon L. B. Nielsen 
1266db522d3aSSimon L. B. Nielsen     OPENSSL_free(wfname);
1267db522d3aSSimon L. B. Nielsen     return NULL;
1268db522d3aSSimon L. B. Nielsen }
1269db522d3aSSimon L. B. Nielsen 
1270db522d3aSSimon L. B. Nielsen void capi_dump_cert(CAPI_CTX * ctx, BIO *out, PCCERT_CONTEXT cert)
1271db522d3aSSimon L. B. Nielsen {
1272db522d3aSSimon L. B. Nielsen     X509 *x;
1273db522d3aSSimon L. B. Nielsen     unsigned char *p;
1274db522d3aSSimon L. B. Nielsen     unsigned long flags = ctx->dump_flags;
12756f9291ceSJung-uk Kim     if (flags & CAPI_DMP_FNAME) {
1276db522d3aSSimon L. B. Nielsen         char *fname;
1277db522d3aSSimon L. B. Nielsen         fname = capi_cert_get_fname(ctx, cert);
12786f9291ceSJung-uk Kim         if (fname) {
1279db522d3aSSimon L. B. Nielsen             BIO_printf(out, "  Friendly Name \"%s\"\n", fname);
1280db522d3aSSimon L. B. Nielsen             OPENSSL_free(fname);
12816f9291ceSJung-uk Kim         } else
1282db522d3aSSimon L. B. Nielsen             BIO_printf(out, "  <No Friendly Name>\n");
1283db522d3aSSimon L. B. Nielsen     }
1284db522d3aSSimon L. B. Nielsen 
1285db522d3aSSimon L. B. Nielsen     p = cert->pbCertEncoded;
1286db522d3aSSimon L. B. Nielsen     x = d2i_X509(NULL, &p, cert->cbCertEncoded);
1287db522d3aSSimon L. B. Nielsen     if (!x)
1288db522d3aSSimon L. B. Nielsen         BIO_printf(out, "  <Can't parse certificate>\n");
12896f9291ceSJung-uk Kim     if (flags & CAPI_DMP_SUMMARY) {
1290db522d3aSSimon L. B. Nielsen         BIO_printf(out, "  Subject: ");
1291db522d3aSSimon L. B. Nielsen         X509_NAME_print_ex(out, X509_get_subject_name(x), 0, XN_FLAG_ONELINE);
1292db522d3aSSimon L. B. Nielsen         BIO_printf(out, "\n  Issuer: ");
1293db522d3aSSimon L. B. Nielsen         X509_NAME_print_ex(out, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE);
1294db522d3aSSimon L. B. Nielsen         BIO_printf(out, "\n");
1295db522d3aSSimon L. B. Nielsen     }
1296db522d3aSSimon L. B. Nielsen     if (flags & CAPI_DMP_FULL)
1297db522d3aSSimon L. B. Nielsen         X509_print_ex(out, x, XN_FLAG_ONELINE, 0);
1298db522d3aSSimon L. B. Nielsen 
12996f9291ceSJung-uk Kim     if (flags & CAPI_DMP_PKEYINFO) {
1300db522d3aSSimon L. B. Nielsen         CRYPT_KEY_PROV_INFO *pinfo;
1301db522d3aSSimon L. B. Nielsen         pinfo = capi_get_prov_info(ctx, cert);
1302db522d3aSSimon L. B. Nielsen         capi_dump_prov_info(ctx, out, pinfo);
1303db522d3aSSimon L. B. Nielsen         if (pinfo)
1304db522d3aSSimon L. B. Nielsen             OPENSSL_free(pinfo);
1305db522d3aSSimon L. B. Nielsen     }
1306db522d3aSSimon L. B. Nielsen 
1307db522d3aSSimon L. B. Nielsen     if (flags & CAPI_DMP_PEM)
1308db522d3aSSimon L. B. Nielsen         PEM_write_bio_X509(out, x);
1309db522d3aSSimon L. B. Nielsen     X509_free(x);
1310db522d3aSSimon L. B. Nielsen }
1311db522d3aSSimon L. B. Nielsen 
1312db522d3aSSimon L. B. Nielsen HCERTSTORE capi_open_store(CAPI_CTX * ctx, char *storename)
1313db522d3aSSimon L. B. Nielsen {
1314db522d3aSSimon L. B. Nielsen     HCERTSTORE hstore;
1315db522d3aSSimon L. B. Nielsen 
1316db522d3aSSimon L. B. Nielsen     if (!storename)
1317db522d3aSSimon L. B. Nielsen         storename = ctx->storename;
1318db522d3aSSimon L. B. Nielsen     if (!storename)
1319db522d3aSSimon L. B. Nielsen         storename = "MY";
1320db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "Opening certificate store %s\n", storename);
1321db522d3aSSimon L. B. Nielsen 
1322db522d3aSSimon L. B. Nielsen     hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0,
1323db522d3aSSimon L. B. Nielsen                            ctx->store_flags, storename);
13246f9291ceSJung-uk Kim     if (!hstore) {
1325db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_OPEN_STORE, CAPI_R_ERROR_OPENING_STORE);
1326db522d3aSSimon L. B. Nielsen         capi_addlasterror();
1327db522d3aSSimon L. B. Nielsen     }
1328db522d3aSSimon L. B. Nielsen     return hstore;
1329db522d3aSSimon L. B. Nielsen }
1330db522d3aSSimon L. B. Nielsen 
1331db522d3aSSimon L. B. Nielsen int capi_list_certs(CAPI_CTX * ctx, BIO *out, char *id)
1332db522d3aSSimon L. B. Nielsen {
1333db522d3aSSimon L. B. Nielsen     char *storename;
1334db522d3aSSimon L. B. Nielsen     int idx;
1335db522d3aSSimon L. B. Nielsen     int ret = 1;
1336db522d3aSSimon L. B. Nielsen     HCERTSTORE hstore;
1337db522d3aSSimon L. B. Nielsen     PCCERT_CONTEXT cert = NULL;
1338db522d3aSSimon L. B. Nielsen 
1339db522d3aSSimon L. B. Nielsen     storename = ctx->storename;
1340db522d3aSSimon L. B. Nielsen     if (!storename)
1341db522d3aSSimon L. B. Nielsen         storename = "MY";
1342db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "Listing certs for store %s\n", storename);
1343db522d3aSSimon L. B. Nielsen 
1344db522d3aSSimon L. B. Nielsen     hstore = capi_open_store(ctx, storename);
1345db522d3aSSimon L. B. Nielsen     if (!hstore)
1346db522d3aSSimon L. B. Nielsen         return 0;
13476f9291ceSJung-uk Kim     if (id) {
1348db522d3aSSimon L. B. Nielsen         cert = capi_find_cert(ctx, id, hstore);
13496f9291ceSJung-uk Kim         if (!cert) {
1350db522d3aSSimon L. B. Nielsen             ret = 0;
1351db522d3aSSimon L. B. Nielsen             goto err;
1352db522d3aSSimon L. B. Nielsen         }
1353db522d3aSSimon L. B. Nielsen         capi_dump_cert(ctx, out, cert);
1354db522d3aSSimon L. B. Nielsen         CertFreeCertificateContext(cert);
13556f9291ceSJung-uk Kim     } else {
13566f9291ceSJung-uk Kim         for (idx = 0;; idx++) {
1357db522d3aSSimon L. B. Nielsen             cert = CertEnumCertificatesInStore(hstore, cert);
1358db522d3aSSimon L. B. Nielsen             if (!cert)
1359db522d3aSSimon L. B. Nielsen                 break;
1360db522d3aSSimon L. B. Nielsen             BIO_printf(out, "Certificate %d\n", idx);
1361db522d3aSSimon L. B. Nielsen             capi_dump_cert(ctx, out, cert);
1362db522d3aSSimon L. B. Nielsen         }
1363db522d3aSSimon L. B. Nielsen     }
1364db522d3aSSimon L. B. Nielsen  err:
1365db522d3aSSimon L. B. Nielsen     CertCloseStore(hstore, 0);
1366db522d3aSSimon L. B. Nielsen     return ret;
1367db522d3aSSimon L. B. Nielsen }
1368db522d3aSSimon L. B. Nielsen 
13696f9291ceSJung-uk Kim static PCCERT_CONTEXT capi_find_cert(CAPI_CTX * ctx, const char *id,
13706f9291ceSJung-uk Kim                                      HCERTSTORE hstore)
1371db522d3aSSimon L. B. Nielsen {
1372db522d3aSSimon L. B. Nielsen     PCCERT_CONTEXT cert = NULL;
1373db522d3aSSimon L. B. Nielsen     char *fname = NULL;
1374db522d3aSSimon L. B. Nielsen     int match;
13756f9291ceSJung-uk Kim     switch (ctx->lookup_method) {
1376db522d3aSSimon L. B. Nielsen     case CAPI_LU_SUBSTR:
1377db522d3aSSimon L. B. Nielsen         return CertFindCertificateInStore(hstore,
1378db522d3aSSimon L. B. Nielsen                                           X509_ASN_ENCODING, 0,
1379db522d3aSSimon L. B. Nielsen                                           CERT_FIND_SUBJECT_STR_A, id, NULL);
1380db522d3aSSimon L. B. Nielsen     case CAPI_LU_FNAME:
13816f9291ceSJung-uk Kim         for (;;) {
1382db522d3aSSimon L. B. Nielsen             cert = CertEnumCertificatesInStore(hstore, cert);
1383db522d3aSSimon L. B. Nielsen             if (!cert)
1384db522d3aSSimon L. B. Nielsen                 return NULL;
1385db522d3aSSimon L. B. Nielsen             fname = capi_cert_get_fname(ctx, cert);
13866f9291ceSJung-uk Kim             if (fname) {
1387db522d3aSSimon L. B. Nielsen                 if (strcmp(fname, id))
1388db522d3aSSimon L. B. Nielsen                     match = 0;
1389db522d3aSSimon L. B. Nielsen                 else
1390db522d3aSSimon L. B. Nielsen                     match = 1;
1391db522d3aSSimon L. B. Nielsen                 OPENSSL_free(fname);
1392db522d3aSSimon L. B. Nielsen                 if (match)
1393db522d3aSSimon L. B. Nielsen                     return cert;
1394db522d3aSSimon L. B. Nielsen             }
1395db522d3aSSimon L. B. Nielsen         }
1396db522d3aSSimon L. B. Nielsen     default:
1397db522d3aSSimon L. B. Nielsen         return NULL;
1398db522d3aSSimon L. B. Nielsen     }
1399db522d3aSSimon L. B. Nielsen }
1400db522d3aSSimon L. B. Nielsen 
1401*7bded2dbSJung-uk Kim static CAPI_KEY *capi_get_key(CAPI_CTX * ctx, const TCHAR *contname,
1402*7bded2dbSJung-uk Kim                               TCHAR *provname, DWORD ptype, DWORD keyspec)
1403db522d3aSSimon L. B. Nielsen {
1404db522d3aSSimon L. B. Nielsen     CAPI_KEY *key;
140509286989SJung-uk Kim     DWORD dwFlags = 0;
1406db522d3aSSimon L. B. Nielsen     key = OPENSSL_malloc(sizeof(CAPI_KEY));
1407*7bded2dbSJung-uk Kim     if (sizeof(TCHAR) == sizeof(char))
1408db522d3aSSimon L. B. Nielsen         CAPI_trace(ctx, "capi_get_key, contname=%s, provname=%s, type=%d\n",
1409db522d3aSSimon L. B. Nielsen                    contname, provname, ptype);
1410*7bded2dbSJung-uk Kim     else if (ctx && ctx->debug_level >= CAPI_DBG_TRACE && ctx->debug_file) {
1411*7bded2dbSJung-uk Kim         /* above 'if' is optimization to minimize malloc-ations */
1412*7bded2dbSJung-uk Kim         char *_contname = wide_to_asc((WCHAR *)contname);
1413*7bded2dbSJung-uk Kim         char *_provname = wide_to_asc((WCHAR *)provname);
1414*7bded2dbSJung-uk Kim 
1415*7bded2dbSJung-uk Kim         CAPI_trace(ctx, "capi_get_key, contname=%s, provname=%s, type=%d\n",
1416*7bded2dbSJung-uk Kim                    _contname, _provname, ptype);
1417*7bded2dbSJung-uk Kim         if (_provname)
1418*7bded2dbSJung-uk Kim             OPENSSL_free(_provname);
1419*7bded2dbSJung-uk Kim         if (_contname)
1420*7bded2dbSJung-uk Kim             OPENSSL_free(_contname);
1421*7bded2dbSJung-uk Kim     }
142209286989SJung-uk Kim     if (ctx->store_flags & CERT_SYSTEM_STORE_LOCAL_MACHINE)
142309286989SJung-uk Kim         dwFlags = CRYPT_MACHINE_KEYSET;
1424*7bded2dbSJung-uk Kim     if (!CryptAcquireContext(&key->hprov, contname, provname, ptype, dwFlags)) {
1425db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_CRYPTACQUIRECONTEXT_ERROR);
1426db522d3aSSimon L. B. Nielsen         capi_addlasterror();
1427db522d3aSSimon L. B. Nielsen         goto err;
1428db522d3aSSimon L. B. Nielsen     }
14296f9291ceSJung-uk Kim     if (!CryptGetUserKey(key->hprov, keyspec, &key->key)) {
1430db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_GETUSERKEY_ERROR);
1431db522d3aSSimon L. B. Nielsen         capi_addlasterror();
1432db522d3aSSimon L. B. Nielsen         CryptReleaseContext(key->hprov, 0);
1433db522d3aSSimon L. B. Nielsen         goto err;
1434db522d3aSSimon L. B. Nielsen     }
1435db522d3aSSimon L. B. Nielsen     key->keyspec = keyspec;
1436db522d3aSSimon L. B. Nielsen     key->pcert = NULL;
1437db522d3aSSimon L. B. Nielsen     return key;
1438db522d3aSSimon L. B. Nielsen 
1439db522d3aSSimon L. B. Nielsen  err:
1440db522d3aSSimon L. B. Nielsen     OPENSSL_free(key);
1441db522d3aSSimon L. B. Nielsen     return NULL;
1442db522d3aSSimon L. B. Nielsen }
1443db522d3aSSimon L. B. Nielsen 
1444db522d3aSSimon L. B. Nielsen static CAPI_KEY *capi_get_cert_key(CAPI_CTX * ctx, PCCERT_CONTEXT cert)
1445db522d3aSSimon L. B. Nielsen {
1446db522d3aSSimon L. B. Nielsen     CAPI_KEY *key = NULL;
1447db522d3aSSimon L. B. Nielsen     CRYPT_KEY_PROV_INFO *pinfo = NULL;
1448db522d3aSSimon L. B. Nielsen     char *provname = NULL, *contname = NULL;
1449db522d3aSSimon L. B. Nielsen     pinfo = capi_get_prov_info(ctx, cert);
1450db522d3aSSimon L. B. Nielsen     if (!pinfo)
1451db522d3aSSimon L. B. Nielsen         goto err;
1452*7bded2dbSJung-uk Kim     if (sizeof(TCHAR) != sizeof(char))
1453*7bded2dbSJung-uk Kim         key = capi_get_key(ctx, (TCHAR *)pinfo->pwszContainerName,
1454*7bded2dbSJung-uk Kim                            (TCHAR *)pinfo->pwszProvName,
1455*7bded2dbSJung-uk Kim                            pinfo->dwProvType, pinfo->dwKeySpec);
1456*7bded2dbSJung-uk Kim     else {
1457db522d3aSSimon L. B. Nielsen         provname = wide_to_asc(pinfo->pwszProvName);
1458db522d3aSSimon L. B. Nielsen         contname = wide_to_asc(pinfo->pwszContainerName);
1459db522d3aSSimon L. B. Nielsen         if (!provname || !contname)
1460db522d3aSSimon L. B. Nielsen             goto err;
1461*7bded2dbSJung-uk Kim         key = capi_get_key(ctx, (TCHAR *)contname, (TCHAR *)provname,
1462db522d3aSSimon L. B. Nielsen                            pinfo->dwProvType, pinfo->dwKeySpec);
1463*7bded2dbSJung-uk Kim     }
1464db522d3aSSimon L. B. Nielsen 
1465db522d3aSSimon L. B. Nielsen  err:
1466db522d3aSSimon L. B. Nielsen     if (pinfo)
1467db522d3aSSimon L. B. Nielsen         OPENSSL_free(pinfo);
1468db522d3aSSimon L. B. Nielsen     if (provname)
1469db522d3aSSimon L. B. Nielsen         OPENSSL_free(provname);
1470db522d3aSSimon L. B. Nielsen     if (contname)
1471db522d3aSSimon L. B. Nielsen         OPENSSL_free(contname);
1472db522d3aSSimon L. B. Nielsen     return key;
1473db522d3aSSimon L. B. Nielsen }
1474db522d3aSSimon L. B. Nielsen 
1475db522d3aSSimon L. B. Nielsen CAPI_KEY *capi_find_key(CAPI_CTX * ctx, const char *id)
1476db522d3aSSimon L. B. Nielsen {
1477db522d3aSSimon L. B. Nielsen     PCCERT_CONTEXT cert;
1478db522d3aSSimon L. B. Nielsen     HCERTSTORE hstore;
1479db522d3aSSimon L. B. Nielsen     CAPI_KEY *key = NULL;
14806f9291ceSJung-uk Kim     switch (ctx->lookup_method) {
1481db522d3aSSimon L. B. Nielsen     case CAPI_LU_SUBSTR:
1482db522d3aSSimon L. B. Nielsen     case CAPI_LU_FNAME:
1483db522d3aSSimon L. B. Nielsen         hstore = capi_open_store(ctx, NULL);
1484db522d3aSSimon L. B. Nielsen         if (!hstore)
1485db522d3aSSimon L. B. Nielsen             return NULL;
1486db522d3aSSimon L. B. Nielsen         cert = capi_find_cert(ctx, id, hstore);
14876f9291ceSJung-uk Kim         if (cert) {
1488db522d3aSSimon L. B. Nielsen             key = capi_get_cert_key(ctx, cert);
1489db522d3aSSimon L. B. Nielsen             CertFreeCertificateContext(cert);
1490db522d3aSSimon L. B. Nielsen         }
1491db522d3aSSimon L. B. Nielsen         CertCloseStore(hstore, 0);
1492db522d3aSSimon L. B. Nielsen         break;
1493db522d3aSSimon L. B. Nielsen 
1494db522d3aSSimon L. B. Nielsen     case CAPI_LU_CONTNAME:
1495*7bded2dbSJung-uk Kim         if (sizeof(TCHAR) != sizeof(char)) {
1496*7bded2dbSJung-uk Kim             WCHAR *contname, *provname;
1497*7bded2dbSJung-uk Kim             DWORD len;
1498*7bded2dbSJung-uk Kim 
1499*7bded2dbSJung-uk Kim             if ((len = MultiByteToWideChar(CP_ACP, 0, id, -1, NULL, 0)) &&
1500*7bded2dbSJung-uk Kim                 (contname = alloca(len * sizeof(WCHAR)),
1501*7bded2dbSJung-uk Kim                  MultiByteToWideChar(CP_ACP, 0, id, -1, contname, len)) &&
1502*7bded2dbSJung-uk Kim                 (len =
1503*7bded2dbSJung-uk Kim                  MultiByteToWideChar(CP_ACP, 0, ctx->cspname, -1, NULL, 0))
1504*7bded2dbSJung-uk Kim                 && (provname =
1505*7bded2dbSJung-uk Kim                     alloca(len * sizeof(WCHAR)), MultiByteToWideChar(CP_ACP,
1506*7bded2dbSJung-uk Kim                                                                      0,
1507*7bded2dbSJung-uk Kim                                                                      ctx->cspname,
1508*7bded2dbSJung-uk Kim                                                                      -1,
1509*7bded2dbSJung-uk Kim                                                                      provname,
1510*7bded2dbSJung-uk Kim                                                                      len)))
1511*7bded2dbSJung-uk Kim                 key =
1512*7bded2dbSJung-uk Kim                     capi_get_key(ctx, (TCHAR *)contname, (TCHAR *)provname,
1513*7bded2dbSJung-uk Kim                                  ctx->csptype, ctx->keytype);
1514*7bded2dbSJung-uk Kim         } else
1515*7bded2dbSJung-uk Kim             key = capi_get_key(ctx, (TCHAR *)id,
1516*7bded2dbSJung-uk Kim                                (TCHAR *)ctx->cspname,
1517*7bded2dbSJung-uk Kim                                ctx->csptype, ctx->keytype);
1518db522d3aSSimon L. B. Nielsen         break;
1519db522d3aSSimon L. B. Nielsen     }
1520db522d3aSSimon L. B. Nielsen 
1521db522d3aSSimon L. B. Nielsen     return key;
1522db522d3aSSimon L. B. Nielsen }
1523db522d3aSSimon L. B. Nielsen 
1524db522d3aSSimon L. B. Nielsen void capi_free_key(CAPI_KEY * key)
1525db522d3aSSimon L. B. Nielsen {
1526db522d3aSSimon L. B. Nielsen     if (!key)
1527db522d3aSSimon L. B. Nielsen         return;
1528db522d3aSSimon L. B. Nielsen     CryptDestroyKey(key->key);
1529db522d3aSSimon L. B. Nielsen     CryptReleaseContext(key->hprov, 0);
1530db522d3aSSimon L. B. Nielsen     if (key->pcert)
1531db522d3aSSimon L. B. Nielsen         CertFreeCertificateContext(key->pcert);
1532db522d3aSSimon L. B. Nielsen     OPENSSL_free(key);
1533db522d3aSSimon L. B. Nielsen }
1534db522d3aSSimon L. B. Nielsen 
1535db522d3aSSimon L. B. Nielsen /* Initialize a CAPI_CTX structure */
1536db522d3aSSimon L. B. Nielsen 
1537db522d3aSSimon L. B. Nielsen static CAPI_CTX *capi_ctx_new()
1538db522d3aSSimon L. B. Nielsen {
1539db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
1540db522d3aSSimon L. B. Nielsen     ctx = OPENSSL_malloc(sizeof(CAPI_CTX));
15416f9291ceSJung-uk Kim     if (!ctx) {
1542db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_CTX_NEW, ERR_R_MALLOC_FAILURE);
1543db522d3aSSimon L. B. Nielsen         return NULL;
1544db522d3aSSimon L. B. Nielsen     }
1545db522d3aSSimon L. B. Nielsen     ctx->cspname = NULL;
1546db522d3aSSimon L. B. Nielsen     ctx->csptype = PROV_RSA_FULL;
1547db522d3aSSimon L. B. Nielsen     ctx->dump_flags = CAPI_DMP_SUMMARY | CAPI_DMP_FNAME;
1548db522d3aSSimon L. B. Nielsen     ctx->keytype = AT_KEYEXCHANGE;
1549db522d3aSSimon L. B. Nielsen     ctx->storename = NULL;
1550db522d3aSSimon L. B. Nielsen     ctx->ssl_client_store = NULL;
1551db522d3aSSimon L. B. Nielsen     ctx->store_flags = CERT_STORE_OPEN_EXISTING_FLAG |
15526f9291ceSJung-uk Kim         CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_CURRENT_USER;
1553db522d3aSSimon L. B. Nielsen     ctx->lookup_method = CAPI_LU_SUBSTR;
1554db522d3aSSimon L. B. Nielsen     ctx->debug_level = 0;
1555db522d3aSSimon L. B. Nielsen     ctx->debug_file = NULL;
1556db522d3aSSimon L. B. Nielsen     ctx->client_cert_select = cert_select_simple;
1557db522d3aSSimon L. B. Nielsen     return ctx;
1558db522d3aSSimon L. B. Nielsen }
1559db522d3aSSimon L. B. Nielsen 
1560db522d3aSSimon L. B. Nielsen static void capi_ctx_free(CAPI_CTX * ctx)
1561db522d3aSSimon L. B. Nielsen {
1562db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "Calling capi_ctx_free with %lx\n", ctx);
1563db522d3aSSimon L. B. Nielsen     if (!ctx)
1564db522d3aSSimon L. B. Nielsen         return;
1565db522d3aSSimon L. B. Nielsen     if (ctx->cspname)
1566db522d3aSSimon L. B. Nielsen         OPENSSL_free(ctx->cspname);
1567db522d3aSSimon L. B. Nielsen     if (ctx->debug_file)
1568db522d3aSSimon L. B. Nielsen         OPENSSL_free(ctx->debug_file);
1569db522d3aSSimon L. B. Nielsen     if (ctx->storename)
1570db522d3aSSimon L. B. Nielsen         OPENSSL_free(ctx->storename);
1571db522d3aSSimon L. B. Nielsen     if (ctx->ssl_client_store)
1572db522d3aSSimon L. B. Nielsen         OPENSSL_free(ctx->ssl_client_store);
1573db522d3aSSimon L. B. Nielsen     OPENSSL_free(ctx);
1574db522d3aSSimon L. B. Nielsen }
1575db522d3aSSimon L. B. Nielsen 
15766f9291ceSJung-uk Kim static int capi_ctx_set_provname(CAPI_CTX * ctx, LPSTR pname, DWORD type,
15776f9291ceSJung-uk Kim                                  int check)
1578db522d3aSSimon L. B. Nielsen {
1579db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "capi_ctx_set_provname, name=%s, type=%d\n", pname, type);
15806f9291ceSJung-uk Kim     if (check) {
1581db522d3aSSimon L. B. Nielsen         HCRYPTPROV hprov;
1582*7bded2dbSJung-uk Kim         LPTSTR name = NULL;
1583*7bded2dbSJung-uk Kim 
1584*7bded2dbSJung-uk Kim         if (sizeof(TCHAR) != sizeof(char)) {
1585*7bded2dbSJung-uk Kim             DWORD len;
1586*7bded2dbSJung-uk Kim             if ((len = MultiByteToWideChar(CP_ACP, 0, pname, -1, NULL, 0))) {
1587*7bded2dbSJung-uk Kim                 name = alloca(len * sizeof(WCHAR));
1588*7bded2dbSJung-uk Kim                 MultiByteToWideChar(CP_ACP, 0, pname, -1, (WCHAR *)name, len);
1589*7bded2dbSJung-uk Kim             }
1590*7bded2dbSJung-uk Kim         } else
1591*7bded2dbSJung-uk Kim             name = (TCHAR *)pname;
1592*7bded2dbSJung-uk Kim 
1593*7bded2dbSJung-uk Kim         if (!name || !CryptAcquireContext(&hprov, NULL, name, type,
15946f9291ceSJung-uk Kim                                           CRYPT_VERIFYCONTEXT)) {
15956f9291ceSJung-uk Kim             CAPIerr(CAPI_F_CAPI_CTX_SET_PROVNAME,
15966f9291ceSJung-uk Kim                     CAPI_R_CRYPTACQUIRECONTEXT_ERROR);
1597db522d3aSSimon L. B. Nielsen             capi_addlasterror();
1598db522d3aSSimon L. B. Nielsen             return 0;
1599db522d3aSSimon L. B. Nielsen         }
1600db522d3aSSimon L. B. Nielsen         CryptReleaseContext(hprov, 0);
1601db522d3aSSimon L. B. Nielsen     }
160212de4ed2SJung-uk Kim     if (ctx->cspname)
160312de4ed2SJung-uk Kim         OPENSSL_free(ctx->cspname);
1604db522d3aSSimon L. B. Nielsen     ctx->cspname = BUF_strdup(pname);
1605db522d3aSSimon L. B. Nielsen     ctx->csptype = type;
1606db522d3aSSimon L. B. Nielsen     return 1;
1607db522d3aSSimon L. B. Nielsen }
1608db522d3aSSimon L. B. Nielsen 
1609db522d3aSSimon L. B. Nielsen static int capi_ctx_set_provname_idx(CAPI_CTX * ctx, int idx)
1610db522d3aSSimon L. B. Nielsen {
1611db522d3aSSimon L. B. Nielsen     LPSTR pname;
1612db522d3aSSimon L. B. Nielsen     DWORD type;
161312de4ed2SJung-uk Kim     int res;
1614db522d3aSSimon L. B. Nielsen     if (capi_get_provname(ctx, &pname, &type, idx) != 1)
1615db522d3aSSimon L. B. Nielsen         return 0;
161612de4ed2SJung-uk Kim     res = capi_ctx_set_provname(ctx, pname, type, 0);
161712de4ed2SJung-uk Kim     OPENSSL_free(pname);
161812de4ed2SJung-uk Kim     return res;
1619db522d3aSSimon L. B. Nielsen }
1620db522d3aSSimon L. B. Nielsen 
1621db522d3aSSimon L. B. Nielsen static int cert_issuer_match(STACK_OF(X509_NAME) *ca_dn, X509 *x)
1622db522d3aSSimon L. B. Nielsen {
1623db522d3aSSimon L. B. Nielsen     int i;
1624db522d3aSSimon L. B. Nielsen     X509_NAME *nm;
1625db522d3aSSimon L. B. Nielsen     /* Special case: empty list: match anything */
1626db522d3aSSimon L. B. Nielsen     if (sk_X509_NAME_num(ca_dn) <= 0)
1627db522d3aSSimon L. B. Nielsen         return 1;
16286f9291ceSJung-uk Kim     for (i = 0; i < sk_X509_NAME_num(ca_dn); i++) {
1629db522d3aSSimon L. B. Nielsen         nm = sk_X509_NAME_value(ca_dn, i);
1630db522d3aSSimon L. B. Nielsen         if (!X509_NAME_cmp(nm, X509_get_issuer_name(x)))
1631db522d3aSSimon L. B. Nielsen             return 1;
1632db522d3aSSimon L. B. Nielsen     }
1633db522d3aSSimon L. B. Nielsen     return 0;
1634db522d3aSSimon L. B. Nielsen }
1635db522d3aSSimon L. B. Nielsen 
1636db522d3aSSimon L. B. Nielsen static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl,
16376f9291ceSJung-uk Kim                                      STACK_OF(X509_NAME) *ca_dn, X509 **pcert,
16386f9291ceSJung-uk Kim                                      EVP_PKEY **pkey, STACK_OF(X509) **pother,
16396f9291ceSJung-uk Kim                                      UI_METHOD *ui_method,
16406f9291ceSJung-uk Kim                                      void *callback_data)
1641db522d3aSSimon L. B. Nielsen {
1642db522d3aSSimon L. B. Nielsen     STACK_OF(X509) *certs = NULL;
1643db522d3aSSimon L. B. Nielsen     X509 *x;
1644db522d3aSSimon L. B. Nielsen     char *storename;
1645db522d3aSSimon L. B. Nielsen     const char *p;
1646db522d3aSSimon L. B. Nielsen     int i, client_cert_idx;
1647db522d3aSSimon L. B. Nielsen     HCERTSTORE hstore;
1648db522d3aSSimon L. B. Nielsen     PCCERT_CONTEXT cert = NULL, excert = NULL;
1649db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
1650db522d3aSSimon L. B. Nielsen     CAPI_KEY *key;
1651db522d3aSSimon L. B. Nielsen     ctx = ENGINE_get_ex_data(e, capi_idx);
1652db522d3aSSimon L. B. Nielsen 
1653db522d3aSSimon L. B. Nielsen     *pcert = NULL;
1654db522d3aSSimon L. B. Nielsen     *pkey = NULL;
1655db522d3aSSimon L. B. Nielsen 
1656db522d3aSSimon L. B. Nielsen     storename = ctx->ssl_client_store;
1657db522d3aSSimon L. B. Nielsen     if (!storename)
1658db522d3aSSimon L. B. Nielsen         storename = "MY";
1659db522d3aSSimon L. B. Nielsen 
1660db522d3aSSimon L. B. Nielsen     hstore = capi_open_store(ctx, storename);
1661db522d3aSSimon L. B. Nielsen     if (!hstore)
1662db522d3aSSimon L. B. Nielsen         return 0;
1663db522d3aSSimon L. B. Nielsen     /* Enumerate all certificates collect any matches */
16646f9291ceSJung-uk Kim     for (i = 0;; i++) {
1665db522d3aSSimon L. B. Nielsen         cert = CertEnumCertificatesInStore(hstore, cert);
1666db522d3aSSimon L. B. Nielsen         if (!cert)
1667db522d3aSSimon L. B. Nielsen             break;
1668db522d3aSSimon L. B. Nielsen         p = cert->pbCertEncoded;
1669db522d3aSSimon L. B. Nielsen         x = d2i_X509(NULL, &p, cert->cbCertEncoded);
16706f9291ceSJung-uk Kim         if (!x) {
1671db522d3aSSimon L. B. Nielsen             CAPI_trace(ctx, "Can't Parse Certificate %d\n", i);
1672db522d3aSSimon L. B. Nielsen             continue;
1673db522d3aSSimon L. B. Nielsen         }
1674db522d3aSSimon L. B. Nielsen         if (cert_issuer_match(ca_dn, x)
16756f9291ceSJung-uk Kim             && X509_check_purpose(x, X509_PURPOSE_SSL_CLIENT, 0)) {
1676db522d3aSSimon L. B. Nielsen             key = capi_get_cert_key(ctx, cert);
16776f9291ceSJung-uk Kim             if (!key) {
1678db522d3aSSimon L. B. Nielsen                 X509_free(x);
1679db522d3aSSimon L. B. Nielsen                 continue;
1680db522d3aSSimon L. B. Nielsen             }
16816f9291ceSJung-uk Kim             /*
16826f9291ceSJung-uk Kim              * Match found: attach extra data to it so we can retrieve the
16836f9291ceSJung-uk Kim              * key later.
1684db522d3aSSimon L. B. Nielsen              */
1685db522d3aSSimon L. B. Nielsen             excert = CertDuplicateCertificateContext(cert);
1686db522d3aSSimon L. B. Nielsen             key->pcert = excert;
1687db522d3aSSimon L. B. Nielsen             X509_set_ex_data(x, cert_capi_idx, key);
1688db522d3aSSimon L. B. Nielsen 
1689db522d3aSSimon L. B. Nielsen             if (!certs)
1690db522d3aSSimon L. B. Nielsen                 certs = sk_X509_new_null();
1691db522d3aSSimon L. B. Nielsen 
1692db522d3aSSimon L. B. Nielsen             sk_X509_push(certs, x);
16936f9291ceSJung-uk Kim         } else
1694db522d3aSSimon L. B. Nielsen             X509_free(x);
1695db522d3aSSimon L. B. Nielsen 
1696db522d3aSSimon L. B. Nielsen     }
1697db522d3aSSimon L. B. Nielsen 
1698db522d3aSSimon L. B. Nielsen     if (cert)
1699db522d3aSSimon L. B. Nielsen         CertFreeCertificateContext(cert);
1700db522d3aSSimon L. B. Nielsen     if (hstore)
1701db522d3aSSimon L. B. Nielsen         CertCloseStore(hstore, 0);
1702db522d3aSSimon L. B. Nielsen 
1703db522d3aSSimon L. B. Nielsen     if (!certs)
1704db522d3aSSimon L. B. Nielsen         return 0;
1705db522d3aSSimon L. B. Nielsen 
1706db522d3aSSimon L. B. Nielsen     /* Select the appropriate certificate */
1707db522d3aSSimon L. B. Nielsen 
1708db522d3aSSimon L. B. Nielsen     client_cert_idx = ctx->client_cert_select(e, ssl, certs);
1709db522d3aSSimon L. B. Nielsen 
1710db522d3aSSimon L. B. Nielsen     /* Set the selected certificate and free the rest */
1711db522d3aSSimon L. B. Nielsen 
17126f9291ceSJung-uk Kim     for (i = 0; i < sk_X509_num(certs); i++) {
1713db522d3aSSimon L. B. Nielsen         x = sk_X509_value(certs, i);
1714db522d3aSSimon L. B. Nielsen         if (i == client_cert_idx)
1715db522d3aSSimon L. B. Nielsen             *pcert = x;
17166f9291ceSJung-uk Kim         else {
1717db522d3aSSimon L. B. Nielsen             key = X509_get_ex_data(x, cert_capi_idx);
1718db522d3aSSimon L. B. Nielsen             capi_free_key(key);
1719db522d3aSSimon L. B. Nielsen             X509_free(x);
1720db522d3aSSimon L. B. Nielsen         }
1721db522d3aSSimon L. B. Nielsen     }
1722db522d3aSSimon L. B. Nielsen 
1723db522d3aSSimon L. B. Nielsen     sk_X509_free(certs);
1724db522d3aSSimon L. B. Nielsen 
1725db522d3aSSimon L. B. Nielsen     if (!*pcert)
1726db522d3aSSimon L. B. Nielsen         return 0;
1727db522d3aSSimon L. B. Nielsen 
1728db522d3aSSimon L. B. Nielsen     /* Setup key for selected certificate */
1729db522d3aSSimon L. B. Nielsen 
1730db522d3aSSimon L. B. Nielsen     key = X509_get_ex_data(*pcert, cert_capi_idx);
1731db522d3aSSimon L. B. Nielsen     *pkey = capi_get_pkey(e, key);
1732db522d3aSSimon L. B. Nielsen     X509_set_ex_data(*pcert, cert_capi_idx, NULL);
1733db522d3aSSimon L. B. Nielsen 
1734db522d3aSSimon L. B. Nielsen     return 1;
1735db522d3aSSimon L. B. Nielsen 
1736db522d3aSSimon L. B. Nielsen }
1737db522d3aSSimon L. B. Nielsen 
1738db522d3aSSimon L. B. Nielsen /* Simple client cert selection function: always select first */
1739db522d3aSSimon L. B. Nielsen 
1740db522d3aSSimon L. B. Nielsen static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs)
1741db522d3aSSimon L. B. Nielsen {
1742db522d3aSSimon L. B. Nielsen     return 0;
1743db522d3aSSimon L. B. Nielsen }
1744db522d3aSSimon L. B. Nielsen 
1745db522d3aSSimon L. B. Nielsen # ifdef OPENSSL_CAPIENG_DIALOG
1746db522d3aSSimon L. B. Nielsen 
17476f9291ceSJung-uk Kim /*
17486f9291ceSJung-uk Kim  * More complex cert selection function, using standard function
1749db522d3aSSimon L. B. Nielsen  * CryptUIDlgSelectCertificateFromStore() to produce a dialog box.
1750db522d3aSSimon L. B. Nielsen  */
1751db522d3aSSimon L. B. Nielsen 
17526f9291ceSJung-uk Kim /*
17536f9291ceSJung-uk Kim  * Definitions which are in cryptuiapi.h but this is not present in older
1754db522d3aSSimon L. B. Nielsen  * versions of headers.
1755db522d3aSSimon L. B. Nielsen  */
1756db522d3aSSimon L. B. Nielsen 
1757db522d3aSSimon L. B. Nielsen #  ifndef CRYPTUI_SELECT_LOCATION_COLUMN
1758db522d3aSSimon L. B. Nielsen #   define CRYPTUI_SELECT_LOCATION_COLUMN                   0x000000010
1759db522d3aSSimon L. B. Nielsen #   define CRYPTUI_SELECT_INTENDEDUSE_COLUMN                0x000000004
1760db522d3aSSimon L. B. Nielsen #  endif
1761db522d3aSSimon L. B. Nielsen 
1762db522d3aSSimon L. B. Nielsen #  define dlg_title L"OpenSSL Application SSL Client Certificate Selection"
1763db522d3aSSimon L. B. Nielsen #  define dlg_prompt L"Select a certificate to use for authentication"
1764db522d3aSSimon L. B. Nielsen #  define dlg_columns      CRYPTUI_SELECT_LOCATION_COLUMN \
1765db522d3aSSimon L. B. Nielsen                         |CRYPTUI_SELECT_INTENDEDUSE_COLUMN
1766db522d3aSSimon L. B. Nielsen 
1767db522d3aSSimon L. B. Nielsen static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs)
1768db522d3aSSimon L. B. Nielsen {
1769db522d3aSSimon L. B. Nielsen     X509 *x;
1770db522d3aSSimon L. B. Nielsen     HCERTSTORE dstore;
1771db522d3aSSimon L. B. Nielsen     PCCERT_CONTEXT cert;
1772db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
1773db522d3aSSimon L. B. Nielsen     CAPI_KEY *key;
1774db522d3aSSimon L. B. Nielsen     HWND hwnd;
1775db522d3aSSimon L. B. Nielsen     int i, idx = -1;
1776db522d3aSSimon L. B. Nielsen     if (sk_X509_num(certs) == 1)
1777db522d3aSSimon L. B. Nielsen         return 0;
1778db522d3aSSimon L. B. Nielsen     ctx = ENGINE_get_ex_data(e, capi_idx);
1779db522d3aSSimon L. B. Nielsen     /* Create an in memory store of certificates */
1780db522d3aSSimon L. B. Nielsen     dstore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1781db522d3aSSimon L. B. Nielsen                            CERT_STORE_CREATE_NEW_FLAG, NULL);
17826f9291ceSJung-uk Kim     if (!dstore) {
1783db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_CREATING_STORE);
1784db522d3aSSimon L. B. Nielsen         capi_addlasterror();
1785db522d3aSSimon L. B. Nielsen         goto err;
1786db522d3aSSimon L. B. Nielsen     }
1787db522d3aSSimon L. B. Nielsen     /* Add all certificates to store */
17886f9291ceSJung-uk Kim     for (i = 0; i < sk_X509_num(certs); i++) {
1789db522d3aSSimon L. B. Nielsen         x = sk_X509_value(certs, i);
1790db522d3aSSimon L. B. Nielsen         key = X509_get_ex_data(x, cert_capi_idx);
1791db522d3aSSimon L. B. Nielsen 
1792db522d3aSSimon L. B. Nielsen         if (!CertAddCertificateContextToStore(dstore, key->pcert,
17936f9291ceSJung-uk Kim                                               CERT_STORE_ADD_NEW, NULL)) {
1794db522d3aSSimon L. B. Nielsen             CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_ADDING_CERT);
1795db522d3aSSimon L. B. Nielsen             capi_addlasterror();
1796db522d3aSSimon L. B. Nielsen             goto err;
1797db522d3aSSimon L. B. Nielsen         }
1798db522d3aSSimon L. B. Nielsen 
1799db522d3aSSimon L. B. Nielsen     }
1800db522d3aSSimon L. B. Nielsen     hwnd = GetForegroundWindow();
1801db522d3aSSimon L. B. Nielsen     if (!hwnd)
1802db522d3aSSimon L. B. Nielsen         hwnd = GetActiveWindow();
1803db522d3aSSimon L. B. Nielsen     if (!hwnd && ctx->getconswindow)
1804db522d3aSSimon L. B. Nielsen         hwnd = ctx->getconswindow();
1805db522d3aSSimon L. B. Nielsen     /* Call dialog to select one */
1806db522d3aSSimon L. B. Nielsen     cert = ctx->certselectdlg(dstore, hwnd, dlg_title, dlg_prompt,
1807db522d3aSSimon L. B. Nielsen                               dlg_columns, 0, NULL);
1808db522d3aSSimon L. B. Nielsen 
1809db522d3aSSimon L. B. Nielsen     /* Find matching cert from list */
18106f9291ceSJung-uk Kim     if (cert) {
18116f9291ceSJung-uk Kim         for (i = 0; i < sk_X509_num(certs); i++) {
1812db522d3aSSimon L. B. Nielsen             x = sk_X509_value(certs, i);
1813db522d3aSSimon L. B. Nielsen             key = X509_get_ex_data(x, cert_capi_idx);
18146f9291ceSJung-uk Kim             if (CertCompareCertificate
18156f9291ceSJung-uk Kim                 (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, cert->pCertInfo,
18166f9291ceSJung-uk Kim                  key->pcert->pCertInfo)) {
1817db522d3aSSimon L. B. Nielsen                 idx = i;
1818db522d3aSSimon L. B. Nielsen                 break;
1819db522d3aSSimon L. B. Nielsen             }
1820db522d3aSSimon L. B. Nielsen         }
1821db522d3aSSimon L. B. Nielsen     }
1822db522d3aSSimon L. B. Nielsen 
1823db522d3aSSimon L. B. Nielsen  err:
1824db522d3aSSimon L. B. Nielsen     if (dstore)
1825db522d3aSSimon L. B. Nielsen         CertCloseStore(dstore, 0);
1826db522d3aSSimon L. B. Nielsen     return idx;
1827db522d3aSSimon L. B. Nielsen 
1828db522d3aSSimon L. B. Nielsen }
1829db522d3aSSimon L. B. Nielsen # endif
1830db522d3aSSimon L. B. Nielsen 
18311f13597dSJung-uk Kim #else                           /* !__COMPILE_CAPIENG */
1832db522d3aSSimon L. B. Nielsen # include <openssl/engine.h>
1833db522d3aSSimon L. B. Nielsen # ifndef OPENSSL_NO_DYNAMIC_ENGINE
1834db522d3aSSimon L. B. Nielsen OPENSSL_EXPORT
18351f13597dSJung-uk Kim     int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns);
18361f13597dSJung-uk Kim OPENSSL_EXPORT
18376f9291ceSJung-uk Kim     int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns)
18386f9291ceSJung-uk Kim {
18396f9291ceSJung-uk Kim     return 0;
18406f9291ceSJung-uk Kim }
18416f9291ceSJung-uk Kim 
1842db522d3aSSimon L. B. Nielsen IMPLEMENT_DYNAMIC_CHECK_FN()
18431f13597dSJung-uk Kim # else
18446f9291ceSJung-uk Kim void ENGINE_load_capi(void)
18456f9291ceSJung-uk Kim {
18466f9291ceSJung-uk Kim }
1847db522d3aSSimon L. B. Nielsen # endif
1848db522d3aSSimon L. B. Nielsen #endif
1849