xref: /freebsd/crypto/openssl/engines/e_capi.c (revision 4c6a0400b9d2b61156387f94d9adbc5f9baa5415)
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>
577bded2dbSJung-uk Kim #include <stdlib.h>
587bded2dbSJung-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 
647bded2dbSJung-uk Kim #  include <openssl/buffer.h>
657bded2dbSJung-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 
727bded2dbSJung-uk Kim #  include <windows.h>
73db522d3aSSimon L. B. Nielsen #  include <wincrypt.h>
747bded2dbSJung-uk Kim #  include <malloc.h>
757bded2dbSJung-uk Kim #  ifndef alloca
767bded2dbSJung-uk Kim #   define alloca _alloca
777bded2dbSJung-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 
117*4c6a0400SJung-uk Kim # ifndef ALG_SID_SHA_256
118*4c6a0400SJung-uk Kim #  define ALG_SID_SHA_256                 12
119*4c6a0400SJung-uk Kim # endif
120*4c6a0400SJung-uk Kim # ifndef ALG_SID_SHA_384
121*4c6a0400SJung-uk Kim #  define ALG_SID_SHA_384                 13
122*4c6a0400SJung-uk Kim # endif
123*4c6a0400SJung-uk Kim # ifndef ALG_SID_SHA_512
124*4c6a0400SJung-uk Kim #  define ALG_SID_SHA_512                 14
125*4c6a0400SJung-uk Kim # endif
126*4c6a0400SJung-uk Kim 
127*4c6a0400SJung-uk Kim # ifndef CALG_SHA_256
128*4c6a0400SJung-uk Kim #  define CALG_SHA_256            (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_256)
129*4c6a0400SJung-uk Kim # endif
130*4c6a0400SJung-uk Kim # ifndef CALG_SHA_384
131*4c6a0400SJung-uk Kim #  define CALG_SHA_384            (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_384)
132*4c6a0400SJung-uk Kim # endif
133*4c6a0400SJung-uk Kim # ifndef CALG_SHA_512
134*4c6a0400SJung-uk Kim #  define CALG_SHA_512            (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_512)
135*4c6a0400SJung-uk Kim # endif
136*4c6a0400SJung-uk Kim 
137db522d3aSSimon L. B. Nielsen # include <openssl/engine.h>
138db522d3aSSimon L. B. Nielsen # include <openssl/pem.h>
139db522d3aSSimon L. B. Nielsen # include <openssl/x509v3.h>
140db522d3aSSimon L. B. Nielsen 
141db522d3aSSimon L. B. Nielsen # include "e_capi_err.h"
142db522d3aSSimon L. B. Nielsen # include "e_capi_err.c"
143db522d3aSSimon L. B. Nielsen 
144db522d3aSSimon L. B. Nielsen static const char *engine_capi_id = "capi";
145db522d3aSSimon L. B. Nielsen static const char *engine_capi_name = "CryptoAPI ENGINE";
146db522d3aSSimon L. B. Nielsen 
147db522d3aSSimon L. B. Nielsen typedef struct CAPI_CTX_st CAPI_CTX;
148db522d3aSSimon L. B. Nielsen typedef struct CAPI_KEY_st CAPI_KEY;
149db522d3aSSimon L. B. Nielsen 
150db522d3aSSimon L. B. Nielsen static void capi_addlasterror(void);
151db522d3aSSimon L. B. Nielsen static void capi_adderror(DWORD err);
152db522d3aSSimon L. B. Nielsen 
153db522d3aSSimon L. B. Nielsen static void CAPI_trace(CAPI_CTX * ctx, char *format, ...);
154db522d3aSSimon L. B. Nielsen 
155db522d3aSSimon L. B. Nielsen static int capi_list_providers(CAPI_CTX * ctx, BIO *out);
156db522d3aSSimon L. B. Nielsen static int capi_list_containers(CAPI_CTX * ctx, BIO *out);
157db522d3aSSimon L. B. Nielsen int capi_list_certs(CAPI_CTX * ctx, BIO *out, char *storename);
158db522d3aSSimon L. B. Nielsen void capi_free_key(CAPI_KEY * key);
159db522d3aSSimon L. B. Nielsen 
1606f9291ceSJung-uk Kim static PCCERT_CONTEXT capi_find_cert(CAPI_CTX * ctx, const char *id,
1616f9291ceSJung-uk Kim                                      HCERTSTORE hstore);
162db522d3aSSimon L. B. Nielsen 
163db522d3aSSimon L. B. Nielsen CAPI_KEY *capi_find_key(CAPI_CTX * ctx, const char *id);
164db522d3aSSimon L. B. Nielsen 
165db522d3aSSimon L. B. Nielsen static EVP_PKEY *capi_load_privkey(ENGINE *eng, const char *key_id,
166db522d3aSSimon L. B. Nielsen                                    UI_METHOD *ui_method, void *callback_data);
1676f9291ceSJung-uk Kim static int capi_rsa_sign(int dtype, const unsigned char *m,
1686f9291ceSJung-uk Kim                          unsigned int m_len, unsigned char *sigret,
1696f9291ceSJung-uk Kim                          unsigned int *siglen, const RSA *rsa);
170db522d3aSSimon L. B. Nielsen static int capi_rsa_priv_enc(int flen, const unsigned char *from,
171db522d3aSSimon L. B. Nielsen                              unsigned char *to, RSA *rsa, int padding);
172db522d3aSSimon L. B. Nielsen static int capi_rsa_priv_dec(int flen, const unsigned char *from,
173db522d3aSSimon L. B. Nielsen                              unsigned char *to, RSA *rsa, int padding);
174db522d3aSSimon L. B. Nielsen static int capi_rsa_free(RSA *rsa);
175db522d3aSSimon L. B. Nielsen 
176db522d3aSSimon L. B. Nielsen static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen,
177db522d3aSSimon L. B. Nielsen                                  DSA *dsa);
178db522d3aSSimon L. B. Nielsen static int capi_dsa_free(DSA *dsa);
179db522d3aSSimon L. B. Nielsen 
180db522d3aSSimon L. B. Nielsen static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl,
1816f9291ceSJung-uk Kim                                      STACK_OF(X509_NAME) *ca_dn, X509 **pcert,
1826f9291ceSJung-uk Kim                                      EVP_PKEY **pkey, STACK_OF(X509) **pother,
1836f9291ceSJung-uk Kim                                      UI_METHOD *ui_method,
1846f9291ceSJung-uk Kim                                      void *callback_data);
185db522d3aSSimon L. B. Nielsen 
186db522d3aSSimon L. B. Nielsen static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
187db522d3aSSimon L. B. Nielsen # ifdef OPENSSL_CAPIENG_DIALOG
188db522d3aSSimon L. B. Nielsen static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
189db522d3aSSimon L. B. Nielsen # endif
190db522d3aSSimon L. B. Nielsen 
191db522d3aSSimon L. B. Nielsen typedef PCCERT_CONTEXT(WINAPI *CERTDLG) (HCERTSTORE, HWND, LPCWSTR,
1926f9291ceSJung-uk Kim                                          LPCWSTR, DWORD, DWORD, void *);
193db522d3aSSimon L. B. Nielsen typedef HWND(WINAPI *GETCONSWIN) (void);
194db522d3aSSimon L. B. Nielsen 
1956f9291ceSJung-uk Kim /*
1966f9291ceSJung-uk Kim  * This structure contains CAPI ENGINE specific data: it contains various
1976f9291ceSJung-uk Kim  * global options and affects how other functions behave.
198db522d3aSSimon L. B. Nielsen  */
199db522d3aSSimon L. B. Nielsen 
200db522d3aSSimon L. B. Nielsen # define CAPI_DBG_TRACE  2
201db522d3aSSimon L. B. Nielsen # define CAPI_DBG_ERROR  1
202db522d3aSSimon L. B. Nielsen 
203db522d3aSSimon L. B. Nielsen struct CAPI_CTX_st {
204db522d3aSSimon L. B. Nielsen     int debug_level;
205db522d3aSSimon L. B. Nielsen     char *debug_file;
206db522d3aSSimon L. B. Nielsen     /* Parameters to use for container lookup */
207db522d3aSSimon L. B. Nielsen     DWORD keytype;
2086a599222SSimon L. B. Nielsen     LPSTR cspname;
209db522d3aSSimon L. B. Nielsen     DWORD csptype;
210db522d3aSSimon L. B. Nielsen     /* Certificate store name to use */
2116a599222SSimon L. B. Nielsen     LPSTR storename;
2126a599222SSimon L. B. Nielsen     LPSTR ssl_client_store;
213db522d3aSSimon L. B. Nielsen     /* System store flags */
214db522d3aSSimon L. B. Nielsen     DWORD store_flags;
215db522d3aSSimon L. B. Nielsen /* Lookup string meanings in load_private_key */
216db522d3aSSimon L. B. Nielsen /* Substring of subject: uses "storename" */
2176a599222SSimon L. B. Nielsen # define CAPI_LU_SUBSTR          1
218db522d3aSSimon L. B. Nielsen /* Friendly name: uses storename */
2196a599222SSimon L. B. Nielsen # define CAPI_LU_FNAME           2
220db522d3aSSimon L. B. Nielsen /* Container name: uses cspname, keytype */
2216a599222SSimon L. B. Nielsen # define CAPI_LU_CONTNAME        3
222db522d3aSSimon L. B. Nielsen     int lookup_method;
223db522d3aSSimon L. B. Nielsen /* Info to dump with dumpcerts option */
224db522d3aSSimon L. B. Nielsen /* Issuer and serial name strings */
225db522d3aSSimon L. B. Nielsen # define CAPI_DMP_SUMMARY        0x1
226db522d3aSSimon L. B. Nielsen /* Friendly name */
227db522d3aSSimon L. B. Nielsen # define CAPI_DMP_FNAME          0x2
228db522d3aSSimon L. B. Nielsen /* Full X509_print dump */
229db522d3aSSimon L. B. Nielsen # define CAPI_DMP_FULL           0x4
230db522d3aSSimon L. B. Nielsen /* Dump PEM format certificate */
231db522d3aSSimon L. B. Nielsen # define CAPI_DMP_PEM            0x8
232db522d3aSSimon L. B. Nielsen /* Dump pseudo key (if possible) */
233db522d3aSSimon L. B. Nielsen # define CAPI_DMP_PSKEY          0x10
234db522d3aSSimon L. B. Nielsen /* Dump key info (if possible) */
235db522d3aSSimon L. B. Nielsen # define CAPI_DMP_PKEYINFO       0x20
236db522d3aSSimon L. B. Nielsen     DWORD dump_flags;
237db522d3aSSimon L. B. Nielsen     int (*client_cert_select) (ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
238db522d3aSSimon L. B. Nielsen     CERTDLG certselectdlg;
239db522d3aSSimon L. B. Nielsen     GETCONSWIN getconswindow;
240db522d3aSSimon L. B. Nielsen };
241db522d3aSSimon L. B. Nielsen 
242db522d3aSSimon L. B. Nielsen static CAPI_CTX *capi_ctx_new();
243db522d3aSSimon L. B. Nielsen static void capi_ctx_free(CAPI_CTX * ctx);
2446f9291ceSJung-uk Kim static int capi_ctx_set_provname(CAPI_CTX * ctx, LPSTR pname, DWORD type,
2456f9291ceSJung-uk Kim                                  int check);
246db522d3aSSimon L. B. Nielsen static int capi_ctx_set_provname_idx(CAPI_CTX * ctx, int idx);
247db522d3aSSimon L. B. Nielsen 
248db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LIST_CERTS             ENGINE_CMD_BASE
249db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LOOKUP_CERT            (ENGINE_CMD_BASE + 1)
250db522d3aSSimon L. B. Nielsen # define CAPI_CMD_DEBUG_LEVEL            (ENGINE_CMD_BASE + 2)
251db522d3aSSimon L. B. Nielsen # define CAPI_CMD_DEBUG_FILE             (ENGINE_CMD_BASE + 3)
252db522d3aSSimon L. B. Nielsen # define CAPI_CMD_KEYTYPE                (ENGINE_CMD_BASE + 4)
253db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LIST_CSPS              (ENGINE_CMD_BASE + 5)
254db522d3aSSimon L. B. Nielsen # define CAPI_CMD_SET_CSP_IDX            (ENGINE_CMD_BASE + 6)
255db522d3aSSimon L. B. Nielsen # define CAPI_CMD_SET_CSP_NAME           (ENGINE_CMD_BASE + 7)
256db522d3aSSimon L. B. Nielsen # define CAPI_CMD_SET_CSP_TYPE           (ENGINE_CMD_BASE + 8)
257db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LIST_CONTAINERS        (ENGINE_CMD_BASE + 9)
258db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LIST_OPTIONS           (ENGINE_CMD_BASE + 10)
259db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LOOKUP_METHOD          (ENGINE_CMD_BASE + 11)
260db522d3aSSimon L. B. Nielsen # define CAPI_CMD_STORE_NAME             (ENGINE_CMD_BASE + 12)
261db522d3aSSimon L. B. Nielsen # define CAPI_CMD_STORE_FLAGS            (ENGINE_CMD_BASE + 13)
262db522d3aSSimon L. B. Nielsen 
263db522d3aSSimon L. B. Nielsen static const ENGINE_CMD_DEFN capi_cmd_defns[] = {
264db522d3aSSimon L. B. Nielsen     {CAPI_CMD_LIST_CERTS,
265db522d3aSSimon L. B. Nielsen      "list_certs",
266db522d3aSSimon L. B. Nielsen      "List all certificates in store",
267db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NO_INPUT},
268db522d3aSSimon L. B. Nielsen     {CAPI_CMD_LOOKUP_CERT,
269db522d3aSSimon L. B. Nielsen      "lookup_cert",
270db522d3aSSimon L. B. Nielsen      "Lookup and output certificates",
271db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_STRING},
272db522d3aSSimon L. B. Nielsen     {CAPI_CMD_DEBUG_LEVEL,
273db522d3aSSimon L. B. Nielsen      "debug_level",
274db522d3aSSimon L. B. Nielsen      "debug level (1=errors, 2=trace)",
275db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NUMERIC},
276db522d3aSSimon L. B. Nielsen     {CAPI_CMD_DEBUG_FILE,
277db522d3aSSimon L. B. Nielsen      "debug_file",
278db522d3aSSimon L. B. Nielsen      "debugging filename)",
279db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_STRING},
280db522d3aSSimon L. B. Nielsen     {CAPI_CMD_KEYTYPE,
281db522d3aSSimon L. B. Nielsen      "key_type",
282db522d3aSSimon L. B. Nielsen      "Key type: 1=AT_KEYEXCHANGE (default), 2=AT_SIGNATURE",
283db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NUMERIC},
284db522d3aSSimon L. B. Nielsen     {CAPI_CMD_LIST_CSPS,
285db522d3aSSimon L. B. Nielsen      "list_csps",
286db522d3aSSimon L. B. Nielsen      "List all CSPs",
287db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NO_INPUT},
288db522d3aSSimon L. B. Nielsen     {CAPI_CMD_SET_CSP_IDX,
289db522d3aSSimon L. B. Nielsen      "csp_idx",
290db522d3aSSimon L. B. Nielsen      "Set CSP by index",
291db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NUMERIC},
292db522d3aSSimon L. B. Nielsen     {CAPI_CMD_SET_CSP_NAME,
293db522d3aSSimon L. B. Nielsen      "csp_name",
294db522d3aSSimon L. B. Nielsen      "Set CSP name, (default CSP used if not specified)",
295db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_STRING},
296db522d3aSSimon L. B. Nielsen     {CAPI_CMD_SET_CSP_TYPE,
297db522d3aSSimon L. B. Nielsen      "csp_type",
298db522d3aSSimon L. B. Nielsen      "Set CSP type, (default RSA_PROV_FULL)",
299db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NUMERIC},
300db522d3aSSimon L. B. Nielsen     {CAPI_CMD_LIST_CONTAINERS,
301db522d3aSSimon L. B. Nielsen      "list_containers",
302db522d3aSSimon L. B. Nielsen      "list container names",
303db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NO_INPUT},
304db522d3aSSimon L. B. Nielsen     {CAPI_CMD_LIST_OPTIONS,
305db522d3aSSimon L. B. Nielsen      "list_options",
306db522d3aSSimon L. B. Nielsen      "Set list options (1=summary,2=friendly name, 4=full printout, 8=PEM output, 16=XXX, "
307db522d3aSSimon L. B. Nielsen      "32=private key info)",
308db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NUMERIC},
309db522d3aSSimon L. B. Nielsen     {CAPI_CMD_LOOKUP_METHOD,
310db522d3aSSimon L. B. Nielsen      "lookup_method",
311db522d3aSSimon L. B. Nielsen      "Set key lookup method (1=substring, 2=friendlyname, 3=container name)",
312db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NUMERIC},
313db522d3aSSimon L. B. Nielsen     {CAPI_CMD_STORE_NAME,
314db522d3aSSimon L. B. Nielsen      "store_name",
315db522d3aSSimon L. B. Nielsen      "certificate store name, default \"MY\"",
316db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_STRING},
317db522d3aSSimon L. B. Nielsen     {CAPI_CMD_STORE_FLAGS,
318db522d3aSSimon L. B. Nielsen      "store_flags",
319db522d3aSSimon L. B. Nielsen      "Certificate store flags: 1 = system store",
320db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NUMERIC},
321db522d3aSSimon L. B. Nielsen 
322db522d3aSSimon L. B. Nielsen     {0, NULL, NULL, 0}
323db522d3aSSimon L. B. Nielsen };
324db522d3aSSimon L. B. Nielsen 
325db522d3aSSimon L. B. Nielsen static int capi_idx = -1;
326db522d3aSSimon L. B. Nielsen static int rsa_capi_idx = -1;
327db522d3aSSimon L. B. Nielsen static int dsa_capi_idx = -1;
328db522d3aSSimon L. B. Nielsen static int cert_capi_idx = -1;
329db522d3aSSimon L. B. Nielsen 
330db522d3aSSimon L. B. Nielsen static int capi_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
331db522d3aSSimon L. B. Nielsen {
332db522d3aSSimon L. B. Nielsen     int ret = 1;
333db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
334db522d3aSSimon L. B. Nielsen     BIO *out;
3356f9291ceSJung-uk Kim     if (capi_idx == -1) {
336db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_ENGINE_NOT_INITIALIZED);
337db522d3aSSimon L. B. Nielsen         return 0;
338db522d3aSSimon L. B. Nielsen     }
339db522d3aSSimon L. B. Nielsen     ctx = ENGINE_get_ex_data(e, capi_idx);
340db522d3aSSimon L. B. Nielsen     out = BIO_new_fp(stdout, BIO_NOCLOSE);
3416f9291ceSJung-uk Kim     switch (cmd) {
342db522d3aSSimon L. B. Nielsen     case CAPI_CMD_LIST_CSPS:
343db522d3aSSimon L. B. Nielsen         ret = capi_list_providers(ctx, out);
344db522d3aSSimon L. B. Nielsen         break;
345db522d3aSSimon L. B. Nielsen 
346db522d3aSSimon L. B. Nielsen     case CAPI_CMD_LIST_CERTS:
347db522d3aSSimon L. B. Nielsen         ret = capi_list_certs(ctx, out, NULL);
348db522d3aSSimon L. B. Nielsen         break;
349db522d3aSSimon L. B. Nielsen 
350db522d3aSSimon L. B. Nielsen     case CAPI_CMD_LOOKUP_CERT:
351db522d3aSSimon L. B. Nielsen         ret = capi_list_certs(ctx, out, p);
352db522d3aSSimon L. B. Nielsen         break;
353db522d3aSSimon L. B. Nielsen 
354db522d3aSSimon L. B. Nielsen     case CAPI_CMD_LIST_CONTAINERS:
355db522d3aSSimon L. B. Nielsen         ret = capi_list_containers(ctx, out);
356db522d3aSSimon L. B. Nielsen         break;
357db522d3aSSimon L. B. Nielsen 
358db522d3aSSimon L. B. Nielsen     case CAPI_CMD_STORE_NAME:
359db522d3aSSimon L. B. Nielsen         if (ctx->storename)
360db522d3aSSimon L. B. Nielsen             OPENSSL_free(ctx->storename);
361db522d3aSSimon L. B. Nielsen         ctx->storename = BUF_strdup(p);
362db522d3aSSimon L. B. Nielsen         CAPI_trace(ctx, "Setting store name to %s\n", p);
363db522d3aSSimon L. B. Nielsen         break;
364db522d3aSSimon L. B. Nielsen 
365db522d3aSSimon L. B. Nielsen     case CAPI_CMD_STORE_FLAGS:
3666f9291ceSJung-uk Kim         if (i & 1) {
367db522d3aSSimon L. B. Nielsen             ctx->store_flags |= CERT_SYSTEM_STORE_LOCAL_MACHINE;
368db522d3aSSimon L. B. Nielsen             ctx->store_flags &= ~CERT_SYSTEM_STORE_CURRENT_USER;
3696f9291ceSJung-uk Kim         } else {
370db522d3aSSimon L. B. Nielsen             ctx->store_flags |= CERT_SYSTEM_STORE_CURRENT_USER;
371db522d3aSSimon L. B. Nielsen             ctx->store_flags &= ~CERT_SYSTEM_STORE_LOCAL_MACHINE;
372db522d3aSSimon L. B. Nielsen         }
373db522d3aSSimon L. B. Nielsen         CAPI_trace(ctx, "Setting flags to %d\n", i);
374db522d3aSSimon L. B. Nielsen         break;
375db522d3aSSimon L. B. Nielsen 
376db522d3aSSimon L. B. Nielsen     case CAPI_CMD_DEBUG_LEVEL:
377db522d3aSSimon L. B. Nielsen         ctx->debug_level = (int)i;
378db522d3aSSimon L. B. Nielsen         CAPI_trace(ctx, "Setting debug level to %d\n", ctx->debug_level);
379db522d3aSSimon L. B. Nielsen         break;
380db522d3aSSimon L. B. Nielsen 
381db522d3aSSimon L. B. Nielsen     case CAPI_CMD_DEBUG_FILE:
382db522d3aSSimon L. B. Nielsen         ctx->debug_file = BUF_strdup(p);
383db522d3aSSimon L. B. Nielsen         CAPI_trace(ctx, "Setting debug file to %s\n", ctx->debug_file);
384db522d3aSSimon L. B. Nielsen         break;
385db522d3aSSimon L. B. Nielsen 
386db522d3aSSimon L. B. Nielsen     case CAPI_CMD_KEYTYPE:
387db522d3aSSimon L. B. Nielsen         ctx->keytype = i;
388db522d3aSSimon L. B. Nielsen         CAPI_trace(ctx, "Setting key type to %d\n", ctx->keytype);
389db522d3aSSimon L. B. Nielsen         break;
390db522d3aSSimon L. B. Nielsen 
391db522d3aSSimon L. B. Nielsen     case CAPI_CMD_SET_CSP_IDX:
392db522d3aSSimon L. B. Nielsen         ret = capi_ctx_set_provname_idx(ctx, i);
393db522d3aSSimon L. B. Nielsen         break;
394db522d3aSSimon L. B. Nielsen 
395db522d3aSSimon L. B. Nielsen     case CAPI_CMD_LIST_OPTIONS:
396db522d3aSSimon L. B. Nielsen         ctx->dump_flags = i;
397db522d3aSSimon L. B. Nielsen         break;
398db522d3aSSimon L. B. Nielsen 
399db522d3aSSimon L. B. Nielsen     case CAPI_CMD_LOOKUP_METHOD:
4006f9291ceSJung-uk Kim         if (i < 1 || i > 3) {
401db522d3aSSimon L. B. Nielsen             CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_INVALID_LOOKUP_METHOD);
402db522d3aSSimon L. B. Nielsen             return 0;
403db522d3aSSimon L. B. Nielsen         }
404db522d3aSSimon L. B. Nielsen         ctx->lookup_method = i;
405db522d3aSSimon L. B. Nielsen         break;
406db522d3aSSimon L. B. Nielsen 
407db522d3aSSimon L. B. Nielsen     case CAPI_CMD_SET_CSP_NAME:
408db522d3aSSimon L. B. Nielsen         ret = capi_ctx_set_provname(ctx, p, ctx->csptype, 1);
409db522d3aSSimon L. B. Nielsen         break;
410db522d3aSSimon L. B. Nielsen 
411db522d3aSSimon L. B. Nielsen     case CAPI_CMD_SET_CSP_TYPE:
412db522d3aSSimon L. B. Nielsen         ctx->csptype = i;
413db522d3aSSimon L. B. Nielsen         break;
414db522d3aSSimon L. B. Nielsen 
415db522d3aSSimon L. B. Nielsen     default:
416db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_UNKNOWN_COMMAND);
417db522d3aSSimon L. B. Nielsen         ret = 0;
418db522d3aSSimon L. B. Nielsen     }
419db522d3aSSimon L. B. Nielsen 
420db522d3aSSimon L. B. Nielsen     BIO_free(out);
421db522d3aSSimon L. B. Nielsen     return ret;
422db522d3aSSimon L. B. Nielsen 
423db522d3aSSimon L. B. Nielsen }
424db522d3aSSimon L. B. Nielsen 
4256f9291ceSJung-uk Kim static RSA_METHOD capi_rsa_method = {
426db522d3aSSimon L. B. Nielsen     "CryptoAPI RSA method",
427db522d3aSSimon L. B. Nielsen     0,                          /* pub_enc */
428db522d3aSSimon L. B. Nielsen     0,                          /* pub_dec */
429db522d3aSSimon L. B. Nielsen     capi_rsa_priv_enc,          /* priv_enc */
430db522d3aSSimon L. B. Nielsen     capi_rsa_priv_dec,          /* priv_dec */
431db522d3aSSimon L. B. Nielsen     0,                          /* rsa_mod_exp */
432db522d3aSSimon L. B. Nielsen     0,                          /* bn_mod_exp */
433db522d3aSSimon L. B. Nielsen     0,                          /* init */
434db522d3aSSimon L. B. Nielsen     capi_rsa_free,              /* finish */
435db522d3aSSimon L. B. Nielsen     RSA_FLAG_SIGN_VER,          /* flags */
436db522d3aSSimon L. B. Nielsen     NULL,                       /* app_data */
437db522d3aSSimon L. B. Nielsen     capi_rsa_sign,              /* rsa_sign */
438db522d3aSSimon L. B. Nielsen     0                           /* rsa_verify */
439db522d3aSSimon L. B. Nielsen };
440db522d3aSSimon L. B. Nielsen 
4416f9291ceSJung-uk Kim static DSA_METHOD capi_dsa_method = {
442db522d3aSSimon L. B. Nielsen     "CryptoAPI DSA method",
443db522d3aSSimon L. B. Nielsen     capi_dsa_do_sign,           /* dsa_do_sign */
444db522d3aSSimon L. B. Nielsen     0,                          /* dsa_sign_setup */
445db522d3aSSimon L. B. Nielsen     0,                          /* dsa_do_verify */
446db522d3aSSimon L. B. Nielsen     0,                          /* dsa_mod_exp */
447db522d3aSSimon L. B. Nielsen     0,                          /* bn_mod_exp */
448db522d3aSSimon L. B. Nielsen     0,                          /* init */
449db522d3aSSimon L. B. Nielsen     capi_dsa_free,              /* finish */
450db522d3aSSimon L. B. Nielsen     0,                          /* flags */
451db522d3aSSimon L. B. Nielsen     NULL,                       /* app_data */
452db522d3aSSimon L. B. Nielsen     0,                          /* dsa_paramgen */
453db522d3aSSimon L. B. Nielsen     0                           /* dsa_keygen */
454db522d3aSSimon L. B. Nielsen };
455db522d3aSSimon L. B. Nielsen 
456db522d3aSSimon L. B. Nielsen static int capi_init(ENGINE *e)
457db522d3aSSimon L. B. Nielsen {
458db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
459db522d3aSSimon L. B. Nielsen     const RSA_METHOD *ossl_rsa_meth;
460db522d3aSSimon L. B. Nielsen     const DSA_METHOD *ossl_dsa_meth;
461db522d3aSSimon L. B. Nielsen 
4626f9291ceSJung-uk Kim     if (capi_idx < 0) {
46312de4ed2SJung-uk Kim         capi_idx = ENGINE_get_ex_new_index(0, NULL, NULL, NULL, 0);
46412de4ed2SJung-uk Kim         if (capi_idx < 0)
465db522d3aSSimon L. B. Nielsen             goto memerr;
466db522d3aSSimon L. B. Nielsen 
46712de4ed2SJung-uk Kim         cert_capi_idx = X509_get_ex_new_index(0, NULL, NULL, NULL, 0);
46812de4ed2SJung-uk Kim 
469db522d3aSSimon L. B. Nielsen         /* Setup RSA_METHOD */
470db522d3aSSimon L. B. Nielsen         rsa_capi_idx = RSA_get_ex_new_index(0, NULL, NULL, NULL, 0);
471db522d3aSSimon L. B. Nielsen         ossl_rsa_meth = RSA_PKCS1_SSLeay();
472db522d3aSSimon L. B. Nielsen         capi_rsa_method.rsa_pub_enc = ossl_rsa_meth->rsa_pub_enc;
473db522d3aSSimon L. B. Nielsen         capi_rsa_method.rsa_pub_dec = ossl_rsa_meth->rsa_pub_dec;
474db522d3aSSimon L. B. Nielsen         capi_rsa_method.rsa_mod_exp = ossl_rsa_meth->rsa_mod_exp;
475db522d3aSSimon L. B. Nielsen         capi_rsa_method.bn_mod_exp = ossl_rsa_meth->bn_mod_exp;
476db522d3aSSimon L. B. Nielsen 
477db522d3aSSimon L. B. Nielsen         /* Setup DSA Method */
478db522d3aSSimon L. B. Nielsen         dsa_capi_idx = DSA_get_ex_new_index(0, NULL, NULL, NULL, 0);
479db522d3aSSimon L. B. Nielsen         ossl_dsa_meth = DSA_OpenSSL();
480db522d3aSSimon L. B. Nielsen         capi_dsa_method.dsa_do_verify = ossl_dsa_meth->dsa_do_verify;
481db522d3aSSimon L. B. Nielsen         capi_dsa_method.dsa_mod_exp = ossl_dsa_meth->dsa_mod_exp;
482db522d3aSSimon L. B. Nielsen         capi_dsa_method.bn_mod_exp = ossl_dsa_meth->bn_mod_exp;
48312de4ed2SJung-uk Kim     }
48412de4ed2SJung-uk Kim 
48512de4ed2SJung-uk Kim     ctx = capi_ctx_new();
48612de4ed2SJung-uk Kim     if (!ctx)
48712de4ed2SJung-uk Kim         goto memerr;
48812de4ed2SJung-uk Kim 
48912de4ed2SJung-uk Kim     ENGINE_set_ex_data(e, capi_idx, ctx);
490db522d3aSSimon L. B. Nielsen 
491db522d3aSSimon L. B. Nielsen # ifdef OPENSSL_CAPIENG_DIALOG
492db522d3aSSimon L. B. Nielsen     {
493db522d3aSSimon L. B. Nielsen         HMODULE cryptui = LoadLibrary(TEXT("CRYPTUI.DLL"));
4946a599222SSimon L. B. Nielsen         HMODULE kernel = GetModuleHandle(TEXT("KERNEL32.DLL"));
495db522d3aSSimon L. B. Nielsen         if (cryptui)
4966f9291ceSJung-uk Kim             ctx->certselectdlg =
4976f9291ceSJung-uk Kim                 (CERTDLG) GetProcAddress(cryptui,
4986f9291ceSJung-uk Kim                                          "CryptUIDlgSelectCertificateFromStore");
499db522d3aSSimon L. B. Nielsen         if (kernel)
5006f9291ceSJung-uk Kim             ctx->getconswindow =
5016f9291ceSJung-uk Kim                 (GETCONSWIN) GetProcAddress(kernel, "GetConsoleWindow");
502db522d3aSSimon L. B. Nielsen         if (cryptui && !OPENSSL_isservice())
503db522d3aSSimon L. B. Nielsen             ctx->client_cert_select = cert_select_dialog;
504db522d3aSSimon L. B. Nielsen     }
505db522d3aSSimon L. B. Nielsen # endif
506db522d3aSSimon L. B. Nielsen 
507db522d3aSSimon L. B. Nielsen     return 1;
508db522d3aSSimon L. B. Nielsen 
509db522d3aSSimon L. B. Nielsen  memerr:
510db522d3aSSimon L. B. Nielsen     CAPIerr(CAPI_F_CAPI_INIT, ERR_R_MALLOC_FAILURE);
511db522d3aSSimon L. B. Nielsen     return 0;
512db522d3aSSimon L. B. Nielsen 
513db522d3aSSimon L. B. Nielsen     return 1;
514db522d3aSSimon L. B. Nielsen }
515db522d3aSSimon L. B. Nielsen 
516db522d3aSSimon L. B. Nielsen static int capi_destroy(ENGINE *e)
517db522d3aSSimon L. B. Nielsen {
518db522d3aSSimon L. B. Nielsen     ERR_unload_CAPI_strings();
519db522d3aSSimon L. B. Nielsen     return 1;
520db522d3aSSimon L. B. Nielsen }
521db522d3aSSimon L. B. Nielsen 
522db522d3aSSimon L. B. Nielsen static int capi_finish(ENGINE *e)
523db522d3aSSimon L. B. Nielsen {
524db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
525db522d3aSSimon L. B. Nielsen     ctx = ENGINE_get_ex_data(e, capi_idx);
526db522d3aSSimon L. B. Nielsen     capi_ctx_free(ctx);
527db522d3aSSimon L. B. Nielsen     ENGINE_set_ex_data(e, capi_idx, NULL);
528db522d3aSSimon L. B. Nielsen     return 1;
529db522d3aSSimon L. B. Nielsen }
530db522d3aSSimon L. B. Nielsen 
5316f9291ceSJung-uk Kim /*
5326f9291ceSJung-uk Kim  * CryptoAPI key application data. This contains a handle to the private key
5336f9291ceSJung-uk Kim  * container (for sign operations) and a handle to the key (for decrypt
5346f9291ceSJung-uk Kim  * operations).
535db522d3aSSimon L. B. Nielsen  */
536db522d3aSSimon L. B. Nielsen 
5376f9291ceSJung-uk Kim struct CAPI_KEY_st {
538db522d3aSSimon L. B. Nielsen     /* Associated certificate context (if any) */
539db522d3aSSimon L. B. Nielsen     PCCERT_CONTEXT pcert;
540db522d3aSSimon L. B. Nielsen     HCRYPTPROV hprov;
541db522d3aSSimon L. B. Nielsen     HCRYPTKEY key;
542db522d3aSSimon L. B. Nielsen     DWORD keyspec;
543db522d3aSSimon L. B. Nielsen };
544db522d3aSSimon L. B. Nielsen 
545db522d3aSSimon L. B. Nielsen static int bind_capi(ENGINE *e)
546db522d3aSSimon L. B. Nielsen {
547db522d3aSSimon L. B. Nielsen     if (!ENGINE_set_id(e, engine_capi_id)
548db522d3aSSimon L. B. Nielsen         || !ENGINE_set_name(e, engine_capi_name)
5491f13597dSJung-uk Kim         || !ENGINE_set_flags(e, ENGINE_FLAGS_NO_REGISTER_ALL)
550db522d3aSSimon L. B. Nielsen         || !ENGINE_set_init_function(e, capi_init)
551db522d3aSSimon L. B. Nielsen         || !ENGINE_set_finish_function(e, capi_finish)
552db522d3aSSimon L. B. Nielsen         || !ENGINE_set_destroy_function(e, capi_destroy)
553db522d3aSSimon L. B. Nielsen         || !ENGINE_set_RSA(e, &capi_rsa_method)
554db522d3aSSimon L. B. Nielsen         || !ENGINE_set_DSA(e, &capi_dsa_method)
555db522d3aSSimon L. B. Nielsen         || !ENGINE_set_load_privkey_function(e, capi_load_privkey)
556db522d3aSSimon L. B. Nielsen         || !ENGINE_set_load_ssl_client_cert_function(e,
557db522d3aSSimon L. B. Nielsen                                                      capi_load_ssl_client_cert)
558db522d3aSSimon L. B. Nielsen         || !ENGINE_set_cmd_defns(e, capi_cmd_defns)
559db522d3aSSimon L. B. Nielsen         || !ENGINE_set_ctrl_function(e, capi_ctrl))
560db522d3aSSimon L. B. Nielsen         return 0;
561db522d3aSSimon L. B. Nielsen     ERR_load_CAPI_strings();
562db522d3aSSimon L. B. Nielsen 
563db522d3aSSimon L. B. Nielsen     return 1;
564db522d3aSSimon L. B. Nielsen 
565db522d3aSSimon L. B. Nielsen }
566db522d3aSSimon L. B. Nielsen 
567db522d3aSSimon L. B. Nielsen # ifndef OPENSSL_NO_DYNAMIC_ENGINE
568db522d3aSSimon L. B. Nielsen static int bind_helper(ENGINE *e, const char *id)
569db522d3aSSimon L. B. Nielsen {
570db522d3aSSimon L. B. Nielsen     if (id && (strcmp(id, engine_capi_id) != 0))
571db522d3aSSimon L. B. Nielsen         return 0;
572db522d3aSSimon L. B. Nielsen     if (!bind_capi(e))
573db522d3aSSimon L. B. Nielsen         return 0;
574db522d3aSSimon L. B. Nielsen     return 1;
575db522d3aSSimon L. B. Nielsen }
5766f9291ceSJung-uk Kim 
577db522d3aSSimon L. B. Nielsen IMPLEMENT_DYNAMIC_CHECK_FN()
578db522d3aSSimon L. B. Nielsen     IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
579db522d3aSSimon L. B. Nielsen # else
580db522d3aSSimon L. B. Nielsen static ENGINE *engine_capi(void)
581db522d3aSSimon L. B. Nielsen {
582db522d3aSSimon L. B. Nielsen     ENGINE *ret = ENGINE_new();
583db522d3aSSimon L. B. Nielsen     if (!ret)
584db522d3aSSimon L. B. Nielsen         return NULL;
5856f9291ceSJung-uk Kim     if (!bind_capi(ret)) {
586db522d3aSSimon L. B. Nielsen         ENGINE_free(ret);
587db522d3aSSimon L. B. Nielsen         return NULL;
588db522d3aSSimon L. B. Nielsen     }
589db522d3aSSimon L. B. Nielsen     return ret;
590db522d3aSSimon L. B. Nielsen }
591db522d3aSSimon L. B. Nielsen 
592db522d3aSSimon L. B. Nielsen void ENGINE_load_capi(void)
593db522d3aSSimon L. B. Nielsen {
594db522d3aSSimon L. B. Nielsen     /* Copied from eng_[openssl|dyn].c */
595db522d3aSSimon L. B. Nielsen     ENGINE *toadd = engine_capi();
5966f9291ceSJung-uk Kim     if (!toadd)
5976f9291ceSJung-uk Kim         return;
598db522d3aSSimon L. B. Nielsen     ENGINE_add(toadd);
599db522d3aSSimon L. B. Nielsen     ENGINE_free(toadd);
600db522d3aSSimon L. B. Nielsen     ERR_clear_error();
601db522d3aSSimon L. B. Nielsen }
602db522d3aSSimon L. B. Nielsen # endif
603db522d3aSSimon L. B. Nielsen 
604db522d3aSSimon L. B. Nielsen static int lend_tobn(BIGNUM *bn, unsigned char *bin, int binlen)
605db522d3aSSimon L. B. Nielsen {
606db522d3aSSimon L. B. Nielsen     int i;
6076f9291ceSJung-uk Kim     /*
6086f9291ceSJung-uk Kim      * Reverse buffer in place: since this is a keyblob structure that will
6096f9291ceSJung-uk Kim      * be freed up after conversion anyway it doesn't matter if we change
6106f9291ceSJung-uk Kim      * it.
611db522d3aSSimon L. B. Nielsen      */
6126f9291ceSJung-uk Kim     for (i = 0; i < binlen / 2; i++) {
613db522d3aSSimon L. B. Nielsen         unsigned char c;
614db522d3aSSimon L. B. Nielsen         c = bin[i];
615db522d3aSSimon L. B. Nielsen         bin[i] = bin[binlen - i - 1];
616db522d3aSSimon L. B. Nielsen         bin[binlen - i - 1] = c;
617db522d3aSSimon L. B. Nielsen     }
618db522d3aSSimon L. B. Nielsen 
619db522d3aSSimon L. B. Nielsen     if (!BN_bin2bn(bin, binlen, bn))
620db522d3aSSimon L. B. Nielsen         return 0;
621db522d3aSSimon L. B. Nielsen     return 1;
622db522d3aSSimon L. B. Nielsen }
623db522d3aSSimon L. B. Nielsen 
624db522d3aSSimon L. B. Nielsen /* Given a CAPI_KEY get an EVP_PKEY structure */
625db522d3aSSimon L. B. Nielsen 
626db522d3aSSimon L. B. Nielsen static EVP_PKEY *capi_get_pkey(ENGINE *eng, CAPI_KEY * key)
627db522d3aSSimon L. B. Nielsen {
628db522d3aSSimon L. B. Nielsen     unsigned char *pubkey = NULL;
629db522d3aSSimon L. B. Nielsen     DWORD len;
630db522d3aSSimon L. B. Nielsen     BLOBHEADER *bh;
631db522d3aSSimon L. B. Nielsen     RSA *rkey = NULL;
632db522d3aSSimon L. B. Nielsen     DSA *dkey = NULL;
633db522d3aSSimon L. B. Nielsen     EVP_PKEY *ret = NULL;
6346f9291ceSJung-uk Kim     if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, NULL, &len)) {
635db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_LENGTH_ERROR);
636db522d3aSSimon L. B. Nielsen         capi_addlasterror();
637db522d3aSSimon L. B. Nielsen         return NULL;
638db522d3aSSimon L. B. Nielsen     }
639db522d3aSSimon L. B. Nielsen 
640db522d3aSSimon L. B. Nielsen     pubkey = OPENSSL_malloc(len);
641db522d3aSSimon L. B. Nielsen 
642db522d3aSSimon L. B. Nielsen     if (!pubkey)
643db522d3aSSimon L. B. Nielsen         goto memerr;
644db522d3aSSimon L. B. Nielsen 
6456f9291ceSJung-uk Kim     if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, pubkey, &len)) {
646db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_ERROR);
647db522d3aSSimon L. B. Nielsen         capi_addlasterror();
648db522d3aSSimon L. B. Nielsen         goto err;
649db522d3aSSimon L. B. Nielsen     }
650db522d3aSSimon L. B. Nielsen 
651db522d3aSSimon L. B. Nielsen     bh = (BLOBHEADER *) pubkey;
6526f9291ceSJung-uk Kim     if (bh->bType != PUBLICKEYBLOB) {
653db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_PUBLIC_KEY_BLOB);
654db522d3aSSimon L. B. Nielsen         goto err;
655db522d3aSSimon L. B. Nielsen     }
6566f9291ceSJung-uk Kim     if (bh->aiKeyAlg == CALG_RSA_SIGN || bh->aiKeyAlg == CALG_RSA_KEYX) {
657db522d3aSSimon L. B. Nielsen         RSAPUBKEY *rp;
658db522d3aSSimon L. B. Nielsen         DWORD rsa_modlen;
659db522d3aSSimon L. B. Nielsen         unsigned char *rsa_modulus;
660db522d3aSSimon L. B. Nielsen         rp = (RSAPUBKEY *) (bh + 1);
6616f9291ceSJung-uk Kim         if (rp->magic != 0x31415352) {
662db522d3aSSimon L. B. Nielsen             char magstr[10];
663db522d3aSSimon L. B. Nielsen             BIO_snprintf(magstr, 10, "%lx", rp->magic);
6646f9291ceSJung-uk Kim             CAPIerr(CAPI_F_CAPI_GET_PKEY,
6656f9291ceSJung-uk Kim                     CAPI_R_INVALID_RSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER);
666db522d3aSSimon L. B. Nielsen             ERR_add_error_data(2, "magic=0x", magstr);
667db522d3aSSimon L. B. Nielsen             goto err;
668db522d3aSSimon L. B. Nielsen         }
669db522d3aSSimon L. B. Nielsen         rsa_modulus = (unsigned char *)(rp + 1);
670db522d3aSSimon L. B. Nielsen         rkey = RSA_new_method(eng);
671db522d3aSSimon L. B. Nielsen         if (!rkey)
672db522d3aSSimon L. B. Nielsen             goto memerr;
673db522d3aSSimon L. B. Nielsen 
674db522d3aSSimon L. B. Nielsen         rkey->e = BN_new();
675db522d3aSSimon L. B. Nielsen         rkey->n = BN_new();
676db522d3aSSimon L. B. Nielsen 
677db522d3aSSimon L. B. Nielsen         if (!rkey->e || !rkey->n)
678db522d3aSSimon L. B. Nielsen             goto memerr;
679db522d3aSSimon L. B. Nielsen 
680db522d3aSSimon L. B. Nielsen         if (!BN_set_word(rkey->e, rp->pubexp))
681db522d3aSSimon L. B. Nielsen             goto memerr;
682db522d3aSSimon L. B. Nielsen 
683db522d3aSSimon L. B. Nielsen         rsa_modlen = rp->bitlen / 8;
684db522d3aSSimon L. B. Nielsen         if (!lend_tobn(rkey->n, rsa_modulus, rsa_modlen))
685db522d3aSSimon L. B. Nielsen             goto memerr;
686db522d3aSSimon L. B. Nielsen 
687db522d3aSSimon L. B. Nielsen         RSA_set_ex_data(rkey, rsa_capi_idx, key);
688db522d3aSSimon L. B. Nielsen 
689db522d3aSSimon L. B. Nielsen         if (!(ret = EVP_PKEY_new()))
690db522d3aSSimon L. B. Nielsen             goto memerr;
691db522d3aSSimon L. B. Nielsen 
692db522d3aSSimon L. B. Nielsen         EVP_PKEY_assign_RSA(ret, rkey);
693db522d3aSSimon L. B. Nielsen         rkey = NULL;
694db522d3aSSimon L. B. Nielsen 
6956f9291ceSJung-uk Kim     } else if (bh->aiKeyAlg == CALG_DSS_SIGN) {
696db522d3aSSimon L. B. Nielsen         DSSPUBKEY *dp;
697db522d3aSSimon L. B. Nielsen         DWORD dsa_plen;
698db522d3aSSimon L. B. Nielsen         unsigned char *btmp;
699db522d3aSSimon L. B. Nielsen         dp = (DSSPUBKEY *) (bh + 1);
7006f9291ceSJung-uk Kim         if (dp->magic != 0x31535344) {
701db522d3aSSimon L. B. Nielsen             char magstr[10];
702db522d3aSSimon L. B. Nielsen             BIO_snprintf(magstr, 10, "%lx", dp->magic);
7036f9291ceSJung-uk Kim             CAPIerr(CAPI_F_CAPI_GET_PKEY,
7046f9291ceSJung-uk Kim                     CAPI_R_INVALID_DSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER);
705db522d3aSSimon L. B. Nielsen             ERR_add_error_data(2, "magic=0x", magstr);
706db522d3aSSimon L. B. Nielsen             goto err;
707db522d3aSSimon L. B. Nielsen         }
708db522d3aSSimon L. B. Nielsen         dsa_plen = dp->bitlen / 8;
709db522d3aSSimon L. B. Nielsen         btmp = (unsigned char *)(dp + 1);
710db522d3aSSimon L. B. Nielsen         dkey = DSA_new_method(eng);
711db522d3aSSimon L. B. Nielsen         if (!dkey)
712db522d3aSSimon L. B. Nielsen             goto memerr;
713db522d3aSSimon L. B. Nielsen         dkey->p = BN_new();
714db522d3aSSimon L. B. Nielsen         dkey->q = BN_new();
715db522d3aSSimon L. B. Nielsen         dkey->g = BN_new();
716db522d3aSSimon L. B. Nielsen         dkey->pub_key = BN_new();
717db522d3aSSimon L. B. Nielsen         if (!dkey->p || !dkey->q || !dkey->g || !dkey->pub_key)
718db522d3aSSimon L. B. Nielsen             goto memerr;
719db522d3aSSimon L. B. Nielsen         if (!lend_tobn(dkey->p, btmp, dsa_plen))
720db522d3aSSimon L. B. Nielsen             goto memerr;
721db522d3aSSimon L. B. Nielsen         btmp += dsa_plen;
722db522d3aSSimon L. B. Nielsen         if (!lend_tobn(dkey->q, btmp, 20))
723db522d3aSSimon L. B. Nielsen             goto memerr;
724db522d3aSSimon L. B. Nielsen         btmp += 20;
725db522d3aSSimon L. B. Nielsen         if (!lend_tobn(dkey->g, btmp, dsa_plen))
726db522d3aSSimon L. B. Nielsen             goto memerr;
727db522d3aSSimon L. B. Nielsen         btmp += dsa_plen;
728db522d3aSSimon L. B. Nielsen         if (!lend_tobn(dkey->pub_key, btmp, dsa_plen))
729db522d3aSSimon L. B. Nielsen             goto memerr;
730db522d3aSSimon L. B. Nielsen         btmp += dsa_plen;
731db522d3aSSimon L. B. Nielsen 
732db522d3aSSimon L. B. Nielsen         DSA_set_ex_data(dkey, dsa_capi_idx, key);
733db522d3aSSimon L. B. Nielsen 
734db522d3aSSimon L. B. Nielsen         if (!(ret = EVP_PKEY_new()))
735db522d3aSSimon L. B. Nielsen             goto memerr;
736db522d3aSSimon L. B. Nielsen 
737db522d3aSSimon L. B. Nielsen         EVP_PKEY_assign_DSA(ret, dkey);
738db522d3aSSimon L. B. Nielsen         dkey = NULL;
7396f9291ceSJung-uk Kim     } else {
740db522d3aSSimon L. B. Nielsen         char algstr[10];
741db522d3aSSimon L. B. Nielsen         BIO_snprintf(algstr, 10, "%lx", bh->aiKeyAlg);
7426f9291ceSJung-uk Kim         CAPIerr(CAPI_F_CAPI_GET_PKEY,
7436f9291ceSJung-uk Kim                 CAPI_R_UNSUPPORTED_PUBLIC_KEY_ALGORITHM);
744db522d3aSSimon L. B. Nielsen         ERR_add_error_data(2, "aiKeyAlg=0x", algstr);
745db522d3aSSimon L. B. Nielsen         goto err;
746db522d3aSSimon L. B. Nielsen     }
747db522d3aSSimon L. B. Nielsen 
748db522d3aSSimon L. B. Nielsen  err:
749db522d3aSSimon L. B. Nielsen     if (pubkey)
750db522d3aSSimon L. B. Nielsen         OPENSSL_free(pubkey);
7516f9291ceSJung-uk Kim     if (!ret) {
752db522d3aSSimon L. B. Nielsen         if (rkey)
753db522d3aSSimon L. B. Nielsen             RSA_free(rkey);
754db522d3aSSimon L. B. Nielsen         if (dkey)
755db522d3aSSimon L. B. Nielsen             DSA_free(dkey);
756db522d3aSSimon L. B. Nielsen     }
757db522d3aSSimon L. B. Nielsen 
758db522d3aSSimon L. B. Nielsen     return ret;
759db522d3aSSimon L. B. Nielsen 
760db522d3aSSimon L. B. Nielsen  memerr:
761db522d3aSSimon L. B. Nielsen     CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_MALLOC_FAILURE);
762db522d3aSSimon L. B. Nielsen     goto err;
763db522d3aSSimon L. B. Nielsen 
764db522d3aSSimon L. B. Nielsen }
765db522d3aSSimon L. B. Nielsen 
766db522d3aSSimon L. B. Nielsen static EVP_PKEY *capi_load_privkey(ENGINE *eng, const char *key_id,
767db522d3aSSimon L. B. Nielsen                                    UI_METHOD *ui_method, void *callback_data)
768db522d3aSSimon L. B. Nielsen {
769db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
770db522d3aSSimon L. B. Nielsen     CAPI_KEY *key;
771db522d3aSSimon L. B. Nielsen     EVP_PKEY *ret;
772db522d3aSSimon L. B. Nielsen     ctx = ENGINE_get_ex_data(eng, capi_idx);
773db522d3aSSimon L. B. Nielsen 
7746f9291ceSJung-uk Kim     if (!ctx) {
775db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_LOAD_PRIVKEY, CAPI_R_CANT_FIND_CAPI_CONTEXT);
776db522d3aSSimon L. B. Nielsen         return NULL;
777db522d3aSSimon L. B. Nielsen     }
778db522d3aSSimon L. B. Nielsen 
779db522d3aSSimon L. B. Nielsen     key = capi_find_key(ctx, key_id);
780db522d3aSSimon L. B. Nielsen 
781db522d3aSSimon L. B. Nielsen     if (!key)
782db522d3aSSimon L. B. Nielsen         return NULL;
783db522d3aSSimon L. B. Nielsen 
784db522d3aSSimon L. B. Nielsen     ret = capi_get_pkey(eng, key);
785db522d3aSSimon L. B. Nielsen 
786db522d3aSSimon L. B. Nielsen     if (!ret)
787db522d3aSSimon L. B. Nielsen         capi_free_key(key);
788db522d3aSSimon L. B. Nielsen     return ret;
789db522d3aSSimon L. B. Nielsen 
790db522d3aSSimon L. B. Nielsen }
791db522d3aSSimon L. B. Nielsen 
792db522d3aSSimon L. B. Nielsen /* CryptoAPI RSA operations */
793db522d3aSSimon L. B. Nielsen 
794db522d3aSSimon L. B. Nielsen int capi_rsa_priv_enc(int flen, const unsigned char *from,
795db522d3aSSimon L. B. Nielsen                       unsigned char *to, RSA *rsa, int padding)
796db522d3aSSimon L. B. Nielsen {
797db522d3aSSimon L. B. Nielsen     CAPIerr(CAPI_F_CAPI_RSA_PRIV_ENC, CAPI_R_FUNCTION_NOT_SUPPORTED);
798db522d3aSSimon L. B. Nielsen     return -1;
799db522d3aSSimon L. B. Nielsen }
800db522d3aSSimon L. B. Nielsen 
801db522d3aSSimon L. B. Nielsen int capi_rsa_sign(int dtype, const unsigned char *m, unsigned int m_len,
802db522d3aSSimon L. B. Nielsen                   unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
803db522d3aSSimon L. B. Nielsen {
804db522d3aSSimon L. B. Nielsen     ALG_ID alg;
805db522d3aSSimon L. B. Nielsen     HCRYPTHASH hash;
806db522d3aSSimon L. B. Nielsen     DWORD slen;
807db522d3aSSimon L. B. Nielsen     unsigned int i;
808db522d3aSSimon L. B. Nielsen     int ret = -1;
809db522d3aSSimon L. B. Nielsen     CAPI_KEY *capi_key;
810db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
811db522d3aSSimon L. B. Nielsen 
812db522d3aSSimon L. B. Nielsen     ctx = ENGINE_get_ex_data(rsa->engine, capi_idx);
813db522d3aSSimon L. B. Nielsen 
814db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "Called CAPI_rsa_sign()\n");
815db522d3aSSimon L. B. Nielsen 
816db522d3aSSimon L. B. Nielsen     capi_key = RSA_get_ex_data(rsa, rsa_capi_idx);
8176f9291ceSJung-uk Kim     if (!capi_key) {
818db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_GET_KEY);
819db522d3aSSimon L. B. Nielsen         return -1;
820db522d3aSSimon L. B. Nielsen     }
821db522d3aSSimon L. B. Nielsen /* Convert the signature type to a CryptoAPI algorithm ID */
8226f9291ceSJung-uk Kim     switch (dtype) {
823*4c6a0400SJung-uk Kim     case NID_sha256:
824*4c6a0400SJung-uk Kim         alg = CALG_SHA_256;
825*4c6a0400SJung-uk Kim         break;
826*4c6a0400SJung-uk Kim 
827*4c6a0400SJung-uk Kim     case NID_sha384:
828*4c6a0400SJung-uk Kim         alg = CALG_SHA_384;
829*4c6a0400SJung-uk Kim         break;
830*4c6a0400SJung-uk Kim 
831*4c6a0400SJung-uk Kim     case NID_sha512:
832*4c6a0400SJung-uk Kim         alg = CALG_SHA_512;
833*4c6a0400SJung-uk Kim         break;
834*4c6a0400SJung-uk Kim 
835db522d3aSSimon L. B. Nielsen     case NID_sha1:
836db522d3aSSimon L. B. Nielsen         alg = CALG_SHA1;
837db522d3aSSimon L. B. Nielsen         break;
838db522d3aSSimon L. B. Nielsen 
839db522d3aSSimon L. B. Nielsen     case NID_md5:
840db522d3aSSimon L. B. Nielsen         alg = CALG_MD5;
841db522d3aSSimon L. B. Nielsen         break;
842db522d3aSSimon L. B. Nielsen 
843db522d3aSSimon L. B. Nielsen     case NID_md5_sha1:
844db522d3aSSimon L. B. Nielsen         alg = CALG_SSL3_SHAMD5;
845db522d3aSSimon L. B. Nielsen         break;
846db522d3aSSimon L. B. Nielsen     default:
847db522d3aSSimon L. B. Nielsen         {
848db522d3aSSimon L. B. Nielsen             char algstr[10];
849db522d3aSSimon L. B. Nielsen             BIO_snprintf(algstr, 10, "%lx", dtype);
850db522d3aSSimon L. B. Nielsen             CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_UNSUPPORTED_ALGORITHM_NID);
851db522d3aSSimon L. B. Nielsen             ERR_add_error_data(2, "NID=0x", algstr);
852db522d3aSSimon L. B. Nielsen             return -1;
853db522d3aSSimon L. B. Nielsen         }
854db522d3aSSimon L. B. Nielsen     }
855db522d3aSSimon L. B. Nielsen 
856db522d3aSSimon L. B. Nielsen /* Create the hash object */
8576f9291ceSJung-uk Kim     if (!CryptCreateHash(capi_key->hprov, alg, 0, 0, &hash)) {
858db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT);
859db522d3aSSimon L. B. Nielsen         capi_addlasterror();
860db522d3aSSimon L. B. Nielsen         return -1;
861db522d3aSSimon L. B. Nielsen     }
862db522d3aSSimon L. B. Nielsen /* Set the hash value to the value passed */
863db522d3aSSimon L. B. Nielsen 
8646f9291ceSJung-uk Kim     if (!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)m, 0)) {
865db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_SET_HASH_VALUE);
866db522d3aSSimon L. B. Nielsen         capi_addlasterror();
867db522d3aSSimon L. B. Nielsen         goto err;
868db522d3aSSimon L. B. Nielsen     }
869db522d3aSSimon L. B. Nielsen 
870db522d3aSSimon L. B. Nielsen /* Finally sign it */
871db522d3aSSimon L. B. Nielsen     slen = RSA_size(rsa);
8727bded2dbSJung-uk Kim     if (!CryptSignHash(hash, capi_key->keyspec, NULL, 0, sigret, &slen)) {
873db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_ERROR_SIGNING_HASH);
874db522d3aSSimon L. B. Nielsen         capi_addlasterror();
875db522d3aSSimon L. B. Nielsen         goto err;
8766f9291ceSJung-uk Kim     } else {
877db522d3aSSimon L. B. Nielsen         ret = 1;
878db522d3aSSimon L. B. Nielsen         /* Inplace byte reversal of signature */
8796f9291ceSJung-uk Kim         for (i = 0; i < slen / 2; i++) {
880db522d3aSSimon L. B. Nielsen             unsigned char c;
881db522d3aSSimon L. B. Nielsen             c = sigret[i];
882db522d3aSSimon L. B. Nielsen             sigret[i] = sigret[slen - i - 1];
883db522d3aSSimon L. B. Nielsen             sigret[slen - i - 1] = c;
884db522d3aSSimon L. B. Nielsen         }
885db522d3aSSimon L. B. Nielsen         *siglen = slen;
886db522d3aSSimon L. B. Nielsen     }
887db522d3aSSimon L. B. Nielsen 
888db522d3aSSimon L. B. Nielsen     /* Now cleanup */
889db522d3aSSimon L. B. Nielsen 
890db522d3aSSimon L. B. Nielsen  err:
891db522d3aSSimon L. B. Nielsen     CryptDestroyHash(hash);
892db522d3aSSimon L. B. Nielsen 
893db522d3aSSimon L. B. Nielsen     return ret;
894db522d3aSSimon L. B. Nielsen }
895db522d3aSSimon L. B. Nielsen 
896db522d3aSSimon L. B. Nielsen int capi_rsa_priv_dec(int flen, const unsigned char *from,
897db522d3aSSimon L. B. Nielsen                       unsigned char *to, RSA *rsa, int padding)
898db522d3aSSimon L. B. Nielsen {
899db522d3aSSimon L. B. Nielsen     int i;
900db522d3aSSimon L. B. Nielsen     unsigned char *tmpbuf;
901db522d3aSSimon L. B. Nielsen     CAPI_KEY *capi_key;
902db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
903db522d3aSSimon L. B. Nielsen     ctx = ENGINE_get_ex_data(rsa->engine, capi_idx);
904db522d3aSSimon L. B. Nielsen 
905db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "Called capi_rsa_priv_dec()\n");
906db522d3aSSimon L. B. Nielsen 
907db522d3aSSimon L. B. Nielsen     capi_key = RSA_get_ex_data(rsa, rsa_capi_idx);
9086f9291ceSJung-uk Kim     if (!capi_key) {
909db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_CANT_GET_KEY);
910db522d3aSSimon L. B. Nielsen         return -1;
911db522d3aSSimon L. B. Nielsen     }
912db522d3aSSimon L. B. Nielsen 
9136f9291ceSJung-uk Kim     if (padding != RSA_PKCS1_PADDING) {
914db522d3aSSimon L. B. Nielsen         char errstr[10];
915db522d3aSSimon L. B. Nielsen         BIO_snprintf(errstr, 10, "%d", padding);
916db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_UNSUPPORTED_PADDING);
917db522d3aSSimon L. B. Nielsen         ERR_add_error_data(2, "padding=", errstr);
918db522d3aSSimon L. B. Nielsen         return -1;
919db522d3aSSimon L. B. Nielsen     }
920db522d3aSSimon L. B. Nielsen 
921db522d3aSSimon L. B. Nielsen     /* Create temp reverse order version of input */
9226f9291ceSJung-uk Kim     if (!(tmpbuf = OPENSSL_malloc(flen))) {
923db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, ERR_R_MALLOC_FAILURE);
924db522d3aSSimon L. B. Nielsen         return -1;
925db522d3aSSimon L. B. Nielsen     }
926db522d3aSSimon L. B. Nielsen     for (i = 0; i < flen; i++)
927db522d3aSSimon L. B. Nielsen         tmpbuf[flen - i - 1] = from[i];
928db522d3aSSimon L. B. Nielsen 
929db522d3aSSimon L. B. Nielsen     /* Finally decrypt it */
9306f9291ceSJung-uk Kim     if (!CryptDecrypt(capi_key->key, 0, TRUE, 0, tmpbuf, &flen)) {
931db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_DECRYPT_ERROR);
932db522d3aSSimon L. B. Nielsen         capi_addlasterror();
933db522d3aSSimon L. B. Nielsen         OPENSSL_free(tmpbuf);
934db522d3aSSimon L. B. Nielsen         return -1;
9356f9291ceSJung-uk Kim     } else
9366f9291ceSJung-uk Kim         memcpy(to, tmpbuf, flen);
937db522d3aSSimon L. B. Nielsen 
938db522d3aSSimon L. B. Nielsen     OPENSSL_free(tmpbuf);
939db522d3aSSimon L. B. Nielsen 
940db522d3aSSimon L. B. Nielsen     return flen;
941db522d3aSSimon L. B. Nielsen }
942db522d3aSSimon L. B. Nielsen 
943db522d3aSSimon L. B. Nielsen static int capi_rsa_free(RSA *rsa)
944db522d3aSSimon L. B. Nielsen {
945db522d3aSSimon L. B. Nielsen     CAPI_KEY *capi_key;
946db522d3aSSimon L. B. Nielsen     capi_key = RSA_get_ex_data(rsa, rsa_capi_idx);
947db522d3aSSimon L. B. Nielsen     capi_free_key(capi_key);
948db522d3aSSimon L. B. Nielsen     RSA_set_ex_data(rsa, rsa_capi_idx, 0);
949db522d3aSSimon L. B. Nielsen     return 1;
950db522d3aSSimon L. B. Nielsen }
951db522d3aSSimon L. B. Nielsen 
952db522d3aSSimon L. B. Nielsen /* CryptoAPI DSA operations */
953db522d3aSSimon L. B. Nielsen 
954db522d3aSSimon L. B. Nielsen static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen,
955db522d3aSSimon L. B. Nielsen                                  DSA *dsa)
956db522d3aSSimon L. B. Nielsen {
957db522d3aSSimon L. B. Nielsen     HCRYPTHASH hash;
958db522d3aSSimon L. B. Nielsen     DWORD slen;
959db522d3aSSimon L. B. Nielsen     DSA_SIG *ret = NULL;
960db522d3aSSimon L. B. Nielsen     CAPI_KEY *capi_key;
961db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
962db522d3aSSimon L. B. Nielsen     unsigned char csigbuf[40];
963db522d3aSSimon L. B. Nielsen 
964db522d3aSSimon L. B. Nielsen     ctx = ENGINE_get_ex_data(dsa->engine, capi_idx);
965db522d3aSSimon L. B. Nielsen 
966db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "Called CAPI_dsa_do_sign()\n");
967db522d3aSSimon L. B. Nielsen 
968db522d3aSSimon L. B. Nielsen     capi_key = DSA_get_ex_data(dsa, dsa_capi_idx);
969db522d3aSSimon L. B. Nielsen 
9706f9291ceSJung-uk Kim     if (!capi_key) {
971db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_GET_KEY);
972db522d3aSSimon L. B. Nielsen         return NULL;
973db522d3aSSimon L. B. Nielsen     }
974db522d3aSSimon L. B. Nielsen 
9756f9291ceSJung-uk Kim     if (dlen != 20) {
976db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_INVALID_DIGEST_LENGTH);
977db522d3aSSimon L. B. Nielsen         return NULL;
978db522d3aSSimon L. B. Nielsen     }
979db522d3aSSimon L. B. Nielsen 
980db522d3aSSimon L. B. Nielsen     /* Create the hash object */
9816f9291ceSJung-uk Kim     if (!CryptCreateHash(capi_key->hprov, CALG_SHA1, 0, 0, &hash)) {
982db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT);
983db522d3aSSimon L. B. Nielsen         capi_addlasterror();
984db522d3aSSimon L. B. Nielsen         return NULL;
985db522d3aSSimon L. B. Nielsen     }
986db522d3aSSimon L. B. Nielsen 
987db522d3aSSimon L. B. Nielsen     /* Set the hash value to the value passed */
9886f9291ceSJung-uk Kim     if (!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)digest, 0)) {
989db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_SET_HASH_VALUE);
990db522d3aSSimon L. B. Nielsen         capi_addlasterror();
991db522d3aSSimon L. B. Nielsen         goto err;
992db522d3aSSimon L. B. Nielsen     }
993db522d3aSSimon L. B. Nielsen 
994db522d3aSSimon L. B. Nielsen     /* Finally sign it */
995db522d3aSSimon L. B. Nielsen     slen = sizeof(csigbuf);
9967bded2dbSJung-uk Kim     if (!CryptSignHash(hash, capi_key->keyspec, NULL, 0, csigbuf, &slen)) {
997db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_ERROR_SIGNING_HASH);
998db522d3aSSimon L. B. Nielsen         capi_addlasterror();
999db522d3aSSimon L. B. Nielsen         goto err;
10006f9291ceSJung-uk Kim     } else {
1001db522d3aSSimon L. B. Nielsen         ret = DSA_SIG_new();
1002db522d3aSSimon L. B. Nielsen         if (!ret)
1003db522d3aSSimon L. B. Nielsen             goto err;
1004db522d3aSSimon L. B. Nielsen         ret->r = BN_new();
1005db522d3aSSimon L. B. Nielsen         ret->s = BN_new();
1006db522d3aSSimon L. B. Nielsen         if (!ret->r || !ret->s)
1007db522d3aSSimon L. B. Nielsen             goto err;
1008db522d3aSSimon L. B. Nielsen         if (!lend_tobn(ret->r, csigbuf, 20)
10096f9291ceSJung-uk Kim             || !lend_tobn(ret->s, csigbuf + 20, 20)) {
1010db522d3aSSimon L. B. Nielsen             DSA_SIG_free(ret);
1011db522d3aSSimon L. B. Nielsen             ret = NULL;
1012db522d3aSSimon L. B. Nielsen             goto err;
1013db522d3aSSimon L. B. Nielsen         }
1014db522d3aSSimon L. B. Nielsen     }
1015db522d3aSSimon L. B. Nielsen 
1016db522d3aSSimon L. B. Nielsen     /* Now cleanup */
1017db522d3aSSimon L. B. Nielsen 
1018db522d3aSSimon L. B. Nielsen  err:
1019db522d3aSSimon L. B. Nielsen     OPENSSL_cleanse(csigbuf, 40);
1020db522d3aSSimon L. B. Nielsen     CryptDestroyHash(hash);
1021db522d3aSSimon L. B. Nielsen     return ret;
1022db522d3aSSimon L. B. Nielsen }
1023db522d3aSSimon L. B. Nielsen 
1024db522d3aSSimon L. B. Nielsen static int capi_dsa_free(DSA *dsa)
1025db522d3aSSimon L. B. Nielsen {
1026db522d3aSSimon L. B. Nielsen     CAPI_KEY *capi_key;
1027db522d3aSSimon L. B. Nielsen     capi_key = DSA_get_ex_data(dsa, dsa_capi_idx);
1028db522d3aSSimon L. B. Nielsen     capi_free_key(capi_key);
1029db522d3aSSimon L. B. Nielsen     DSA_set_ex_data(dsa, dsa_capi_idx, 0);
1030db522d3aSSimon L. B. Nielsen     return 1;
1031db522d3aSSimon L. B. Nielsen }
1032db522d3aSSimon L. B. Nielsen 
10336f9291ceSJung-uk Kim static void capi_vtrace(CAPI_CTX * ctx, int level, char *format,
10346f9291ceSJung-uk Kim                         va_list argptr)
1035db522d3aSSimon L. B. Nielsen {
1036db522d3aSSimon L. B. Nielsen     BIO *out;
1037db522d3aSSimon L. B. Nielsen 
1038db522d3aSSimon L. B. Nielsen     if (!ctx || (ctx->debug_level < level) || (!ctx->debug_file))
1039db522d3aSSimon L. B. Nielsen         return;
1040db522d3aSSimon L. B. Nielsen     out = BIO_new_file(ctx->debug_file, "a+");
1041db522d3aSSimon L. B. Nielsen     BIO_vprintf(out, format, argptr);
1042db522d3aSSimon L. B. Nielsen     BIO_free(out);
1043db522d3aSSimon L. B. Nielsen }
1044db522d3aSSimon L. B. Nielsen 
1045db522d3aSSimon L. B. Nielsen static void CAPI_trace(CAPI_CTX * ctx, char *format, ...)
1046db522d3aSSimon L. B. Nielsen {
1047db522d3aSSimon L. B. Nielsen     va_list args;
1048db522d3aSSimon L. B. Nielsen     va_start(args, format);
1049db522d3aSSimon L. B. Nielsen     capi_vtrace(ctx, CAPI_DBG_TRACE, format, args);
1050db522d3aSSimon L. B. Nielsen     va_end(args);
1051db522d3aSSimon L. B. Nielsen }
1052db522d3aSSimon L. B. Nielsen 
1053db522d3aSSimon L. B. Nielsen static void capi_addlasterror(void)
1054db522d3aSSimon L. B. Nielsen {
1055db522d3aSSimon L. B. Nielsen     capi_adderror(GetLastError());
1056db522d3aSSimon L. B. Nielsen }
1057db522d3aSSimon L. B. Nielsen 
1058db522d3aSSimon L. B. Nielsen static void capi_adderror(DWORD err)
1059db522d3aSSimon L. B. Nielsen {
1060db522d3aSSimon L. B. Nielsen     char errstr[10];
1061db522d3aSSimon L. B. Nielsen     BIO_snprintf(errstr, 10, "%lX", err);
1062db522d3aSSimon L. B. Nielsen     ERR_add_error_data(2, "Error code= 0x", errstr);
1063db522d3aSSimon L. B. Nielsen }
1064db522d3aSSimon L. B. Nielsen 
10657bded2dbSJung-uk Kim static char *wide_to_asc(LPCWSTR wstr)
1066db522d3aSSimon L. B. Nielsen {
1067db522d3aSSimon L. B. Nielsen     char *str;
10686a599222SSimon L. B. Nielsen     int len_0, sz;
10696a599222SSimon L. B. Nielsen 
1070db522d3aSSimon L. B. Nielsen     if (!wstr)
1071db522d3aSSimon L. B. Nielsen         return NULL;
10726a599222SSimon L. B. Nielsen     len_0 = (int)wcslen(wstr) + 1; /* WideCharToMultiByte expects int */
10736a599222SSimon L. B. Nielsen     sz = WideCharToMultiByte(CP_ACP, 0, wstr, len_0, NULL, 0, NULL, NULL);
10746f9291ceSJung-uk Kim     if (!sz) {
10756a599222SSimon L. B. Nielsen         CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_WIN32_ERROR);
10766a599222SSimon L. B. Nielsen         return NULL;
10776a599222SSimon L. B. Nielsen     }
10786a599222SSimon L. B. Nielsen     str = OPENSSL_malloc(sz);
10796f9291ceSJung-uk Kim     if (!str) {
1080db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_WIDE_TO_ASC, ERR_R_MALLOC_FAILURE);
1081db522d3aSSimon L. B. Nielsen         return NULL;
1082db522d3aSSimon L. B. Nielsen     }
10836f9291ceSJung-uk Kim     if (!WideCharToMultiByte(CP_ACP, 0, wstr, len_0, str, sz, NULL, NULL)) {
10846a599222SSimon L. B. Nielsen         OPENSSL_free(str);
10856a599222SSimon L. B. Nielsen         CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_WIN32_ERROR);
10866a599222SSimon L. B. Nielsen         return NULL;
10876a599222SSimon L. B. Nielsen     }
1088db522d3aSSimon L. B. Nielsen     return str;
1089db522d3aSSimon L. B. Nielsen }
1090db522d3aSSimon L. B. Nielsen 
10916f9291ceSJung-uk Kim static int capi_get_provname(CAPI_CTX * ctx, LPSTR * pname, DWORD * ptype,
10926f9291ceSJung-uk Kim                              DWORD idx)
1093db522d3aSSimon L. B. Nielsen {
1094db522d3aSSimon L. B. Nielsen     DWORD len, err;
10957bded2dbSJung-uk Kim     LPTSTR name;
1096db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "capi_get_provname, index=%d\n", idx);
10977bded2dbSJung-uk Kim     if (!CryptEnumProviders(idx, NULL, 0, ptype, NULL, &len)) {
1098db522d3aSSimon L. B. Nielsen         err = GetLastError();
1099db522d3aSSimon L. B. Nielsen         if (err == ERROR_NO_MORE_ITEMS)
1100db522d3aSSimon L. B. Nielsen             return 2;
1101db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_PROVNAME, CAPI_R_CRYPTENUMPROVIDERS_ERROR);
1102db522d3aSSimon L. B. Nielsen         capi_adderror(err);
1103db522d3aSSimon L. B. Nielsen         return 0;
1104db522d3aSSimon L. B. Nielsen     }
11057bded2dbSJung-uk Kim     if (sizeof(TCHAR) != sizeof(char))
11067bded2dbSJung-uk Kim         name = alloca(len);
11077bded2dbSJung-uk Kim     else
1108db522d3aSSimon L. B. Nielsen         name = OPENSSL_malloc(len);
11097bded2dbSJung-uk Kim     if (!CryptEnumProviders(idx, NULL, 0, ptype, name, &len)) {
1110db522d3aSSimon L. B. Nielsen         err = GetLastError();
1111db522d3aSSimon L. B. Nielsen         if (err == ERROR_NO_MORE_ITEMS)
1112db522d3aSSimon L. B. Nielsen             return 2;
1113db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_PROVNAME, CAPI_R_CRYPTENUMPROVIDERS_ERROR);
1114db522d3aSSimon L. B. Nielsen         capi_adderror(err);
1115db522d3aSSimon L. B. Nielsen         return 0;
1116db522d3aSSimon L. B. Nielsen     }
11177bded2dbSJung-uk Kim     if (sizeof(TCHAR) != sizeof(char))
11187bded2dbSJung-uk Kim         *pname = wide_to_asc((WCHAR *)name);
11197bded2dbSJung-uk Kim     else
11207bded2dbSJung-uk Kim         *pname = (char *)name;
11217bded2dbSJung-uk Kim     CAPI_trace(ctx, "capi_get_provname, returned name=%s, type=%d\n", *pname,
11226f9291ceSJung-uk Kim                *ptype);
1123db522d3aSSimon L. B. Nielsen 
1124db522d3aSSimon L. B. Nielsen     return 1;
1125db522d3aSSimon L. B. Nielsen }
1126db522d3aSSimon L. B. Nielsen 
1127db522d3aSSimon L. B. Nielsen static int capi_list_providers(CAPI_CTX * ctx, BIO *out)
1128db522d3aSSimon L. B. Nielsen {
1129db522d3aSSimon L. B. Nielsen     DWORD idx, ptype;
1130db522d3aSSimon L. B. Nielsen     int ret;
11316a599222SSimon L. B. Nielsen     LPSTR provname = NULL;
1132db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "capi_list_providers\n");
1133db522d3aSSimon L. B. Nielsen     BIO_printf(out, "Available CSPs:\n");
11346f9291ceSJung-uk Kim     for (idx = 0;; idx++) {
1135db522d3aSSimon L. B. Nielsen         ret = capi_get_provname(ctx, &provname, &ptype, idx);
1136db522d3aSSimon L. B. Nielsen         if (ret == 2)
1137db522d3aSSimon L. B. Nielsen             break;
1138db522d3aSSimon L. B. Nielsen         if (ret == 0)
1139db522d3aSSimon L. B. Nielsen             break;
1140db522d3aSSimon L. B. Nielsen         BIO_printf(out, "%d. %s, type %d\n", idx, provname, ptype);
1141db522d3aSSimon L. B. Nielsen         OPENSSL_free(provname);
1142db522d3aSSimon L. B. Nielsen     }
1143db522d3aSSimon L. B. Nielsen     return 1;
1144db522d3aSSimon L. B. Nielsen }
1145db522d3aSSimon L. B. Nielsen 
1146db522d3aSSimon L. B. Nielsen static int capi_list_containers(CAPI_CTX * ctx, BIO *out)
1147db522d3aSSimon L. B. Nielsen {
1148db522d3aSSimon L. B. Nielsen     int ret = 1;
1149db522d3aSSimon L. B. Nielsen     HCRYPTPROV hprov;
1150db522d3aSSimon L. B. Nielsen     DWORD err, idx, flags, buflen = 0, clen;
1151db522d3aSSimon L. B. Nielsen     LPSTR cname;
11527bded2dbSJung-uk Kim     LPTSTR cspname = NULL;
11537bded2dbSJung-uk Kim 
11546f9291ceSJung-uk Kim     CAPI_trace(ctx, "Listing containers CSP=%s, type = %d\n", ctx->cspname,
11556f9291ceSJung-uk Kim                ctx->csptype);
11567bded2dbSJung-uk Kim     if (ctx->cspname && sizeof(TCHAR) != sizeof(char)) {
11577bded2dbSJung-uk Kim         if ((clen =
11587bded2dbSJung-uk Kim              MultiByteToWideChar(CP_ACP, 0, ctx->cspname, -1, NULL, 0))) {
11597bded2dbSJung-uk Kim             cspname = alloca(clen * sizeof(WCHAR));
11607bded2dbSJung-uk Kim             MultiByteToWideChar(CP_ACP, 0, ctx->cspname, -1, (WCHAR *)cspname,
11617bded2dbSJung-uk Kim                                 clen);
11627bded2dbSJung-uk Kim         }
11637bded2dbSJung-uk Kim         if (!cspname) {
11647bded2dbSJung-uk Kim             CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, ERR_R_MALLOC_FAILURE);
11657bded2dbSJung-uk Kim             capi_addlasterror();
11667bded2dbSJung-uk Kim             return 0;
11677bded2dbSJung-uk Kim         }
11687bded2dbSJung-uk Kim     } else
11697bded2dbSJung-uk Kim         cspname = (TCHAR *)ctx->cspname;
11707bded2dbSJung-uk Kim     if (!CryptAcquireContext
11717bded2dbSJung-uk Kim         (&hprov, NULL, cspname, ctx->csptype, CRYPT_VERIFYCONTEXT)) {
11726f9291ceSJung-uk Kim         CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS,
11736f9291ceSJung-uk Kim                 CAPI_R_CRYPTACQUIRECONTEXT_ERROR);
1174db522d3aSSimon L. B. Nielsen         capi_addlasterror();
1175db522d3aSSimon L. B. Nielsen         return 0;
1176db522d3aSSimon L. B. Nielsen     }
11776f9291ceSJung-uk Kim     if (!CryptGetProvParam
11786f9291ceSJung-uk Kim         (hprov, PP_ENUMCONTAINERS, NULL, &buflen, CRYPT_FIRST)) {
1179db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_ENUMCONTAINERS_ERROR);
1180db522d3aSSimon L. B. Nielsen         capi_addlasterror();
118112de4ed2SJung-uk Kim         CryptReleaseContext(hprov, 0);
1182db522d3aSSimon L. B. Nielsen         return 0;
1183db522d3aSSimon L. B. Nielsen     }
1184db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "Got max container len %d\n", buflen);
1185db522d3aSSimon L. B. Nielsen     if (buflen == 0)
1186db522d3aSSimon L. B. Nielsen         buflen = 1024;
1187db522d3aSSimon L. B. Nielsen     cname = OPENSSL_malloc(buflen);
11886f9291ceSJung-uk Kim     if (!cname) {
1189db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, ERR_R_MALLOC_FAILURE);
1190db522d3aSSimon L. B. Nielsen         goto err;
1191db522d3aSSimon L. B. Nielsen     }
1192db522d3aSSimon L. B. Nielsen 
11936f9291ceSJung-uk Kim     for (idx = 0;; idx++) {
1194db522d3aSSimon L. B. Nielsen         clen = buflen;
1195db522d3aSSimon L. B. Nielsen         cname[0] = 0;
1196db522d3aSSimon L. B. Nielsen 
1197db522d3aSSimon L. B. Nielsen         if (idx == 0)
1198db522d3aSSimon L. B. Nielsen             flags = CRYPT_FIRST;
1199db522d3aSSimon L. B. Nielsen         else
1200db522d3aSSimon L. B. Nielsen             flags = 0;
12017bded2dbSJung-uk Kim         if (!CryptGetProvParam
12027bded2dbSJung-uk Kim             (hprov, PP_ENUMCONTAINERS, (BYTE *) cname, &clen, flags)) {
1203db522d3aSSimon L. B. Nielsen             err = GetLastError();
1204db522d3aSSimon L. B. Nielsen             if (err == ERROR_NO_MORE_ITEMS)
1205db522d3aSSimon L. B. Nielsen                 goto done;
1206db522d3aSSimon L. B. Nielsen             CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_ENUMCONTAINERS_ERROR);
1207db522d3aSSimon L. B. Nielsen             capi_adderror(err);
1208db522d3aSSimon L. B. Nielsen             goto err;
1209db522d3aSSimon L. B. Nielsen         }
12106f9291ceSJung-uk Kim         CAPI_trace(ctx, "Container name %s, len=%d, index=%d, flags=%d\n",
12116f9291ceSJung-uk Kim                    cname, clen, idx, flags);
12126f9291ceSJung-uk Kim         if (!cname[0] && (clen == buflen)) {
1213db522d3aSSimon L. B. Nielsen             CAPI_trace(ctx, "Enumerate bug: using workaround\n");
1214db522d3aSSimon L. B. Nielsen             goto done;
1215db522d3aSSimon L. B. Nielsen         }
1216db522d3aSSimon L. B. Nielsen         BIO_printf(out, "%d. %s\n", idx, cname);
1217db522d3aSSimon L. B. Nielsen     }
1218db522d3aSSimon L. B. Nielsen  err:
1219db522d3aSSimon L. B. Nielsen 
1220db522d3aSSimon L. B. Nielsen     ret = 0;
1221db522d3aSSimon L. B. Nielsen 
1222db522d3aSSimon L. B. Nielsen  done:
1223db522d3aSSimon L. B. Nielsen     if (cname)
1224db522d3aSSimon L. B. Nielsen         OPENSSL_free(cname);
1225db522d3aSSimon L. B. Nielsen     CryptReleaseContext(hprov, 0);
1226db522d3aSSimon L. B. Nielsen 
1227db522d3aSSimon L. B. Nielsen     return ret;
1228db522d3aSSimon L. B. Nielsen }
1229db522d3aSSimon L. B. Nielsen 
1230db522d3aSSimon L. B. Nielsen CRYPT_KEY_PROV_INFO *capi_get_prov_info(CAPI_CTX * ctx, PCCERT_CONTEXT cert)
1231db522d3aSSimon L. B. Nielsen {
1232db522d3aSSimon L. B. Nielsen     DWORD len;
1233db522d3aSSimon L. B. Nielsen     CRYPT_KEY_PROV_INFO *pinfo;
1234db522d3aSSimon L. B. Nielsen 
12356f9291ceSJung-uk Kim     if (!CertGetCertificateContextProperty
12366f9291ceSJung-uk Kim         (cert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &len))
1237db522d3aSSimon L. B. Nielsen         return NULL;
1238db522d3aSSimon L. B. Nielsen     pinfo = OPENSSL_malloc(len);
12396f9291ceSJung-uk Kim     if (!pinfo) {
1240db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_PROV_INFO, ERR_R_MALLOC_FAILURE);
1241db522d3aSSimon L. B. Nielsen         return NULL;
1242db522d3aSSimon L. B. Nielsen     }
12436f9291ceSJung-uk Kim     if (!CertGetCertificateContextProperty
12446f9291ceSJung-uk Kim         (cert, CERT_KEY_PROV_INFO_PROP_ID, pinfo, &len)) {
12456f9291ceSJung-uk Kim         CAPIerr(CAPI_F_CAPI_GET_PROV_INFO,
12466f9291ceSJung-uk Kim                 CAPI_R_ERROR_GETTING_KEY_PROVIDER_INFO);
1247db522d3aSSimon L. B. Nielsen         capi_addlasterror();
1248db522d3aSSimon L. B. Nielsen         OPENSSL_free(pinfo);
1249db522d3aSSimon L. B. Nielsen         return NULL;
1250db522d3aSSimon L. B. Nielsen     }
1251db522d3aSSimon L. B. Nielsen     return pinfo;
1252db522d3aSSimon L. B. Nielsen }
1253db522d3aSSimon L. B. Nielsen 
12546f9291ceSJung-uk Kim static void capi_dump_prov_info(CAPI_CTX * ctx, BIO *out,
12556f9291ceSJung-uk Kim                                 CRYPT_KEY_PROV_INFO * pinfo)
1256db522d3aSSimon L. B. Nielsen {
1257db522d3aSSimon L. B. Nielsen     char *provname = NULL, *contname = NULL;
12586f9291ceSJung-uk Kim     if (!pinfo) {
1259db522d3aSSimon L. B. Nielsen         BIO_printf(out, "  No Private Key\n");
1260db522d3aSSimon L. B. Nielsen         return;
1261db522d3aSSimon L. B. Nielsen     }
1262db522d3aSSimon L. B. Nielsen     provname = wide_to_asc(pinfo->pwszProvName);
1263db522d3aSSimon L. B. Nielsen     contname = wide_to_asc(pinfo->pwszContainerName);
1264db522d3aSSimon L. B. Nielsen     if (!provname || !contname)
1265db522d3aSSimon L. B. Nielsen         goto err;
1266db522d3aSSimon L. B. Nielsen 
1267db522d3aSSimon L. B. Nielsen     BIO_printf(out, "  Private Key Info:\n");
12686f9291ceSJung-uk Kim     BIO_printf(out, "    Provider Name:  %s, Provider Type %d\n", provname,
12696f9291ceSJung-uk Kim                pinfo->dwProvType);
12706f9291ceSJung-uk Kim     BIO_printf(out, "    Container Name: %s, Key Type %d\n", contname,
12716f9291ceSJung-uk Kim                pinfo->dwKeySpec);
1272db522d3aSSimon L. B. Nielsen  err:
1273db522d3aSSimon L. B. Nielsen     if (provname)
1274db522d3aSSimon L. B. Nielsen         OPENSSL_free(provname);
1275db522d3aSSimon L. B. Nielsen     if (contname)
1276db522d3aSSimon L. B. Nielsen         OPENSSL_free(contname);
1277db522d3aSSimon L. B. Nielsen }
1278db522d3aSSimon L. B. Nielsen 
1279db522d3aSSimon L. B. Nielsen char *capi_cert_get_fname(CAPI_CTX * ctx, PCCERT_CONTEXT cert)
1280db522d3aSSimon L. B. Nielsen {
1281db522d3aSSimon L. B. Nielsen     LPWSTR wfname;
1282db522d3aSSimon L. B. Nielsen     DWORD dlen;
1283db522d3aSSimon L. B. Nielsen 
1284db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "capi_cert_get_fname\n");
12856f9291ceSJung-uk Kim     if (!CertGetCertificateContextProperty
12866f9291ceSJung-uk Kim         (cert, CERT_FRIENDLY_NAME_PROP_ID, NULL, &dlen))
1287db522d3aSSimon L. B. Nielsen         return NULL;
1288db522d3aSSimon L. B. Nielsen     wfname = OPENSSL_malloc(dlen);
12896f9291ceSJung-uk Kim     if (CertGetCertificateContextProperty
12906f9291ceSJung-uk Kim         (cert, CERT_FRIENDLY_NAME_PROP_ID, wfname, &dlen)) {
1291db522d3aSSimon L. B. Nielsen         char *fname = wide_to_asc(wfname);
1292db522d3aSSimon L. B. Nielsen         OPENSSL_free(wfname);
1293db522d3aSSimon L. B. Nielsen         return fname;
1294db522d3aSSimon L. B. Nielsen     }
1295db522d3aSSimon L. B. Nielsen     CAPIerr(CAPI_F_CAPI_CERT_GET_FNAME, CAPI_R_ERROR_GETTING_FRIENDLY_NAME);
1296db522d3aSSimon L. B. Nielsen     capi_addlasterror();
1297db522d3aSSimon L. B. Nielsen 
1298db522d3aSSimon L. B. Nielsen     OPENSSL_free(wfname);
1299db522d3aSSimon L. B. Nielsen     return NULL;
1300db522d3aSSimon L. B. Nielsen }
1301db522d3aSSimon L. B. Nielsen 
1302db522d3aSSimon L. B. Nielsen void capi_dump_cert(CAPI_CTX * ctx, BIO *out, PCCERT_CONTEXT cert)
1303db522d3aSSimon L. B. Nielsen {
1304db522d3aSSimon L. B. Nielsen     X509 *x;
1305db522d3aSSimon L. B. Nielsen     unsigned char *p;
1306db522d3aSSimon L. B. Nielsen     unsigned long flags = ctx->dump_flags;
13076f9291ceSJung-uk Kim     if (flags & CAPI_DMP_FNAME) {
1308db522d3aSSimon L. B. Nielsen         char *fname;
1309db522d3aSSimon L. B. Nielsen         fname = capi_cert_get_fname(ctx, cert);
13106f9291ceSJung-uk Kim         if (fname) {
1311db522d3aSSimon L. B. Nielsen             BIO_printf(out, "  Friendly Name \"%s\"\n", fname);
1312db522d3aSSimon L. B. Nielsen             OPENSSL_free(fname);
13136f9291ceSJung-uk Kim         } else
1314db522d3aSSimon L. B. Nielsen             BIO_printf(out, "  <No Friendly Name>\n");
1315db522d3aSSimon L. B. Nielsen     }
1316db522d3aSSimon L. B. Nielsen 
1317db522d3aSSimon L. B. Nielsen     p = cert->pbCertEncoded;
1318db522d3aSSimon L. B. Nielsen     x = d2i_X509(NULL, &p, cert->cbCertEncoded);
1319db522d3aSSimon L. B. Nielsen     if (!x)
1320db522d3aSSimon L. B. Nielsen         BIO_printf(out, "  <Can't parse certificate>\n");
13216f9291ceSJung-uk Kim     if (flags & CAPI_DMP_SUMMARY) {
1322db522d3aSSimon L. B. Nielsen         BIO_printf(out, "  Subject: ");
1323db522d3aSSimon L. B. Nielsen         X509_NAME_print_ex(out, X509_get_subject_name(x), 0, XN_FLAG_ONELINE);
1324db522d3aSSimon L. B. Nielsen         BIO_printf(out, "\n  Issuer: ");
1325db522d3aSSimon L. B. Nielsen         X509_NAME_print_ex(out, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE);
1326db522d3aSSimon L. B. Nielsen         BIO_printf(out, "\n");
1327db522d3aSSimon L. B. Nielsen     }
1328db522d3aSSimon L. B. Nielsen     if (flags & CAPI_DMP_FULL)
1329db522d3aSSimon L. B. Nielsen         X509_print_ex(out, x, XN_FLAG_ONELINE, 0);
1330db522d3aSSimon L. B. Nielsen 
13316f9291ceSJung-uk Kim     if (flags & CAPI_DMP_PKEYINFO) {
1332db522d3aSSimon L. B. Nielsen         CRYPT_KEY_PROV_INFO *pinfo;
1333db522d3aSSimon L. B. Nielsen         pinfo = capi_get_prov_info(ctx, cert);
1334db522d3aSSimon L. B. Nielsen         capi_dump_prov_info(ctx, out, pinfo);
1335db522d3aSSimon L. B. Nielsen         if (pinfo)
1336db522d3aSSimon L. B. Nielsen             OPENSSL_free(pinfo);
1337db522d3aSSimon L. B. Nielsen     }
1338db522d3aSSimon L. B. Nielsen 
1339db522d3aSSimon L. B. Nielsen     if (flags & CAPI_DMP_PEM)
1340db522d3aSSimon L. B. Nielsen         PEM_write_bio_X509(out, x);
1341db522d3aSSimon L. B. Nielsen     X509_free(x);
1342db522d3aSSimon L. B. Nielsen }
1343db522d3aSSimon L. B. Nielsen 
1344db522d3aSSimon L. B. Nielsen HCERTSTORE capi_open_store(CAPI_CTX * ctx, char *storename)
1345db522d3aSSimon L. B. Nielsen {
1346db522d3aSSimon L. B. Nielsen     HCERTSTORE hstore;
1347db522d3aSSimon L. B. Nielsen 
1348db522d3aSSimon L. B. Nielsen     if (!storename)
1349db522d3aSSimon L. B. Nielsen         storename = ctx->storename;
1350db522d3aSSimon L. B. Nielsen     if (!storename)
1351db522d3aSSimon L. B. Nielsen         storename = "MY";
1352db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "Opening certificate store %s\n", storename);
1353db522d3aSSimon L. B. Nielsen 
1354db522d3aSSimon L. B. Nielsen     hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0,
1355db522d3aSSimon L. B. Nielsen                            ctx->store_flags, storename);
13566f9291ceSJung-uk Kim     if (!hstore) {
1357db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_OPEN_STORE, CAPI_R_ERROR_OPENING_STORE);
1358db522d3aSSimon L. B. Nielsen         capi_addlasterror();
1359db522d3aSSimon L. B. Nielsen     }
1360db522d3aSSimon L. B. Nielsen     return hstore;
1361db522d3aSSimon L. B. Nielsen }
1362db522d3aSSimon L. B. Nielsen 
1363db522d3aSSimon L. B. Nielsen int capi_list_certs(CAPI_CTX * ctx, BIO *out, char *id)
1364db522d3aSSimon L. B. Nielsen {
1365db522d3aSSimon L. B. Nielsen     char *storename;
1366db522d3aSSimon L. B. Nielsen     int idx;
1367db522d3aSSimon L. B. Nielsen     int ret = 1;
1368db522d3aSSimon L. B. Nielsen     HCERTSTORE hstore;
1369db522d3aSSimon L. B. Nielsen     PCCERT_CONTEXT cert = NULL;
1370db522d3aSSimon L. B. Nielsen 
1371db522d3aSSimon L. B. Nielsen     storename = ctx->storename;
1372db522d3aSSimon L. B. Nielsen     if (!storename)
1373db522d3aSSimon L. B. Nielsen         storename = "MY";
1374db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "Listing certs for store %s\n", storename);
1375db522d3aSSimon L. B. Nielsen 
1376db522d3aSSimon L. B. Nielsen     hstore = capi_open_store(ctx, storename);
1377db522d3aSSimon L. B. Nielsen     if (!hstore)
1378db522d3aSSimon L. B. Nielsen         return 0;
13796f9291ceSJung-uk Kim     if (id) {
1380db522d3aSSimon L. B. Nielsen         cert = capi_find_cert(ctx, id, hstore);
13816f9291ceSJung-uk Kim         if (!cert) {
1382db522d3aSSimon L. B. Nielsen             ret = 0;
1383db522d3aSSimon L. B. Nielsen             goto err;
1384db522d3aSSimon L. B. Nielsen         }
1385db522d3aSSimon L. B. Nielsen         capi_dump_cert(ctx, out, cert);
1386db522d3aSSimon L. B. Nielsen         CertFreeCertificateContext(cert);
13876f9291ceSJung-uk Kim     } else {
13886f9291ceSJung-uk Kim         for (idx = 0;; idx++) {
1389db522d3aSSimon L. B. Nielsen             cert = CertEnumCertificatesInStore(hstore, cert);
1390db522d3aSSimon L. B. Nielsen             if (!cert)
1391db522d3aSSimon L. B. Nielsen                 break;
1392db522d3aSSimon L. B. Nielsen             BIO_printf(out, "Certificate %d\n", idx);
1393db522d3aSSimon L. B. Nielsen             capi_dump_cert(ctx, out, cert);
1394db522d3aSSimon L. B. Nielsen         }
1395db522d3aSSimon L. B. Nielsen     }
1396db522d3aSSimon L. B. Nielsen  err:
1397db522d3aSSimon L. B. Nielsen     CertCloseStore(hstore, 0);
1398db522d3aSSimon L. B. Nielsen     return ret;
1399db522d3aSSimon L. B. Nielsen }
1400db522d3aSSimon L. B. Nielsen 
14016f9291ceSJung-uk Kim static PCCERT_CONTEXT capi_find_cert(CAPI_CTX * ctx, const char *id,
14026f9291ceSJung-uk Kim                                      HCERTSTORE hstore)
1403db522d3aSSimon L. B. Nielsen {
1404db522d3aSSimon L. B. Nielsen     PCCERT_CONTEXT cert = NULL;
1405db522d3aSSimon L. B. Nielsen     char *fname = NULL;
1406db522d3aSSimon L. B. Nielsen     int match;
14076f9291ceSJung-uk Kim     switch (ctx->lookup_method) {
1408db522d3aSSimon L. B. Nielsen     case CAPI_LU_SUBSTR:
1409db522d3aSSimon L. B. Nielsen         return CertFindCertificateInStore(hstore,
1410db522d3aSSimon L. B. Nielsen                                           X509_ASN_ENCODING, 0,
1411db522d3aSSimon L. B. Nielsen                                           CERT_FIND_SUBJECT_STR_A, id, NULL);
1412db522d3aSSimon L. B. Nielsen     case CAPI_LU_FNAME:
14136f9291ceSJung-uk Kim         for (;;) {
1414db522d3aSSimon L. B. Nielsen             cert = CertEnumCertificatesInStore(hstore, cert);
1415db522d3aSSimon L. B. Nielsen             if (!cert)
1416db522d3aSSimon L. B. Nielsen                 return NULL;
1417db522d3aSSimon L. B. Nielsen             fname = capi_cert_get_fname(ctx, cert);
14186f9291ceSJung-uk Kim             if (fname) {
1419db522d3aSSimon L. B. Nielsen                 if (strcmp(fname, id))
1420db522d3aSSimon L. B. Nielsen                     match = 0;
1421db522d3aSSimon L. B. Nielsen                 else
1422db522d3aSSimon L. B. Nielsen                     match = 1;
1423db522d3aSSimon L. B. Nielsen                 OPENSSL_free(fname);
1424db522d3aSSimon L. B. Nielsen                 if (match)
1425db522d3aSSimon L. B. Nielsen                     return cert;
1426db522d3aSSimon L. B. Nielsen             }
1427db522d3aSSimon L. B. Nielsen         }
1428db522d3aSSimon L. B. Nielsen     default:
1429db522d3aSSimon L. B. Nielsen         return NULL;
1430db522d3aSSimon L. B. Nielsen     }
1431db522d3aSSimon L. B. Nielsen }
1432db522d3aSSimon L. B. Nielsen 
14337bded2dbSJung-uk Kim static CAPI_KEY *capi_get_key(CAPI_CTX * ctx, const TCHAR *contname,
14347bded2dbSJung-uk Kim                               TCHAR *provname, DWORD ptype, DWORD keyspec)
1435db522d3aSSimon L. B. Nielsen {
1436db522d3aSSimon L. B. Nielsen     CAPI_KEY *key;
143709286989SJung-uk Kim     DWORD dwFlags = 0;
1438db522d3aSSimon L. B. Nielsen     key = OPENSSL_malloc(sizeof(CAPI_KEY));
14397bded2dbSJung-uk Kim     if (sizeof(TCHAR) == sizeof(char))
1440db522d3aSSimon L. B. Nielsen         CAPI_trace(ctx, "capi_get_key, contname=%s, provname=%s, type=%d\n",
1441db522d3aSSimon L. B. Nielsen                    contname, provname, ptype);
14427bded2dbSJung-uk Kim     else if (ctx && ctx->debug_level >= CAPI_DBG_TRACE && ctx->debug_file) {
14437bded2dbSJung-uk Kim         /* above 'if' is optimization to minimize malloc-ations */
14447bded2dbSJung-uk Kim         char *_contname = wide_to_asc((WCHAR *)contname);
14457bded2dbSJung-uk Kim         char *_provname = wide_to_asc((WCHAR *)provname);
14467bded2dbSJung-uk Kim 
14477bded2dbSJung-uk Kim         CAPI_trace(ctx, "capi_get_key, contname=%s, provname=%s, type=%d\n",
14487bded2dbSJung-uk Kim                    _contname, _provname, ptype);
14497bded2dbSJung-uk Kim         if (_provname)
14507bded2dbSJung-uk Kim             OPENSSL_free(_provname);
14517bded2dbSJung-uk Kim         if (_contname)
14527bded2dbSJung-uk Kim             OPENSSL_free(_contname);
14537bded2dbSJung-uk Kim     }
145409286989SJung-uk Kim     if (ctx->store_flags & CERT_SYSTEM_STORE_LOCAL_MACHINE)
145509286989SJung-uk Kim         dwFlags = CRYPT_MACHINE_KEYSET;
14567bded2dbSJung-uk Kim     if (!CryptAcquireContext(&key->hprov, contname, provname, ptype, dwFlags)) {
1457db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_CRYPTACQUIRECONTEXT_ERROR);
1458db522d3aSSimon L. B. Nielsen         capi_addlasterror();
1459db522d3aSSimon L. B. Nielsen         goto err;
1460db522d3aSSimon L. B. Nielsen     }
14616f9291ceSJung-uk Kim     if (!CryptGetUserKey(key->hprov, keyspec, &key->key)) {
1462db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_GETUSERKEY_ERROR);
1463db522d3aSSimon L. B. Nielsen         capi_addlasterror();
1464db522d3aSSimon L. B. Nielsen         CryptReleaseContext(key->hprov, 0);
1465db522d3aSSimon L. B. Nielsen         goto err;
1466db522d3aSSimon L. B. Nielsen     }
1467db522d3aSSimon L. B. Nielsen     key->keyspec = keyspec;
1468db522d3aSSimon L. B. Nielsen     key->pcert = NULL;
1469db522d3aSSimon L. B. Nielsen     return key;
1470db522d3aSSimon L. B. Nielsen 
1471db522d3aSSimon L. B. Nielsen  err:
1472db522d3aSSimon L. B. Nielsen     OPENSSL_free(key);
1473db522d3aSSimon L. B. Nielsen     return NULL;
1474db522d3aSSimon L. B. Nielsen }
1475db522d3aSSimon L. B. Nielsen 
1476db522d3aSSimon L. B. Nielsen static CAPI_KEY *capi_get_cert_key(CAPI_CTX * ctx, PCCERT_CONTEXT cert)
1477db522d3aSSimon L. B. Nielsen {
1478db522d3aSSimon L. B. Nielsen     CAPI_KEY *key = NULL;
1479db522d3aSSimon L. B. Nielsen     CRYPT_KEY_PROV_INFO *pinfo = NULL;
1480db522d3aSSimon L. B. Nielsen     char *provname = NULL, *contname = NULL;
1481db522d3aSSimon L. B. Nielsen     pinfo = capi_get_prov_info(ctx, cert);
1482db522d3aSSimon L. B. Nielsen     if (!pinfo)
1483db522d3aSSimon L. B. Nielsen         goto err;
14847bded2dbSJung-uk Kim     if (sizeof(TCHAR) != sizeof(char))
14857bded2dbSJung-uk Kim         key = capi_get_key(ctx, (TCHAR *)pinfo->pwszContainerName,
14867bded2dbSJung-uk Kim                            (TCHAR *)pinfo->pwszProvName,
14877bded2dbSJung-uk Kim                            pinfo->dwProvType, pinfo->dwKeySpec);
14887bded2dbSJung-uk Kim     else {
1489db522d3aSSimon L. B. Nielsen         provname = wide_to_asc(pinfo->pwszProvName);
1490db522d3aSSimon L. B. Nielsen         contname = wide_to_asc(pinfo->pwszContainerName);
1491db522d3aSSimon L. B. Nielsen         if (!provname || !contname)
1492db522d3aSSimon L. B. Nielsen             goto err;
14937bded2dbSJung-uk Kim         key = capi_get_key(ctx, (TCHAR *)contname, (TCHAR *)provname,
1494db522d3aSSimon L. B. Nielsen                            pinfo->dwProvType, pinfo->dwKeySpec);
14957bded2dbSJung-uk Kim     }
1496db522d3aSSimon L. B. Nielsen 
1497db522d3aSSimon L. B. Nielsen  err:
1498db522d3aSSimon L. B. Nielsen     if (pinfo)
1499db522d3aSSimon L. B. Nielsen         OPENSSL_free(pinfo);
1500db522d3aSSimon L. B. Nielsen     if (provname)
1501db522d3aSSimon L. B. Nielsen         OPENSSL_free(provname);
1502db522d3aSSimon L. B. Nielsen     if (contname)
1503db522d3aSSimon L. B. Nielsen         OPENSSL_free(contname);
1504db522d3aSSimon L. B. Nielsen     return key;
1505db522d3aSSimon L. B. Nielsen }
1506db522d3aSSimon L. B. Nielsen 
1507db522d3aSSimon L. B. Nielsen CAPI_KEY *capi_find_key(CAPI_CTX * ctx, const char *id)
1508db522d3aSSimon L. B. Nielsen {
1509db522d3aSSimon L. B. Nielsen     PCCERT_CONTEXT cert;
1510db522d3aSSimon L. B. Nielsen     HCERTSTORE hstore;
1511db522d3aSSimon L. B. Nielsen     CAPI_KEY *key = NULL;
15126f9291ceSJung-uk Kim     switch (ctx->lookup_method) {
1513db522d3aSSimon L. B. Nielsen     case CAPI_LU_SUBSTR:
1514db522d3aSSimon L. B. Nielsen     case CAPI_LU_FNAME:
1515db522d3aSSimon L. B. Nielsen         hstore = capi_open_store(ctx, NULL);
1516db522d3aSSimon L. B. Nielsen         if (!hstore)
1517db522d3aSSimon L. B. Nielsen             return NULL;
1518db522d3aSSimon L. B. Nielsen         cert = capi_find_cert(ctx, id, hstore);
15196f9291ceSJung-uk Kim         if (cert) {
1520db522d3aSSimon L. B. Nielsen             key = capi_get_cert_key(ctx, cert);
1521db522d3aSSimon L. B. Nielsen             CertFreeCertificateContext(cert);
1522db522d3aSSimon L. B. Nielsen         }
1523db522d3aSSimon L. B. Nielsen         CertCloseStore(hstore, 0);
1524db522d3aSSimon L. B. Nielsen         break;
1525db522d3aSSimon L. B. Nielsen 
1526db522d3aSSimon L. B. Nielsen     case CAPI_LU_CONTNAME:
15277bded2dbSJung-uk Kim         if (sizeof(TCHAR) != sizeof(char)) {
15287bded2dbSJung-uk Kim             WCHAR *contname, *provname;
15297bded2dbSJung-uk Kim             DWORD len;
15307bded2dbSJung-uk Kim 
15317bded2dbSJung-uk Kim             if ((len = MultiByteToWideChar(CP_ACP, 0, id, -1, NULL, 0)) &&
15327bded2dbSJung-uk Kim                 (contname = alloca(len * sizeof(WCHAR)),
15337bded2dbSJung-uk Kim                  MultiByteToWideChar(CP_ACP, 0, id, -1, contname, len)) &&
15347bded2dbSJung-uk Kim                 (len =
15357bded2dbSJung-uk Kim                  MultiByteToWideChar(CP_ACP, 0, ctx->cspname, -1, NULL, 0))
15367bded2dbSJung-uk Kim                 && (provname =
15377bded2dbSJung-uk Kim                     alloca(len * sizeof(WCHAR)), MultiByteToWideChar(CP_ACP,
15387bded2dbSJung-uk Kim                                                                      0,
15397bded2dbSJung-uk Kim                                                                      ctx->cspname,
15407bded2dbSJung-uk Kim                                                                      -1,
15417bded2dbSJung-uk Kim                                                                      provname,
15427bded2dbSJung-uk Kim                                                                      len)))
15437bded2dbSJung-uk Kim                 key =
15447bded2dbSJung-uk Kim                     capi_get_key(ctx, (TCHAR *)contname, (TCHAR *)provname,
15457bded2dbSJung-uk Kim                                  ctx->csptype, ctx->keytype);
15467bded2dbSJung-uk Kim         } else
15477bded2dbSJung-uk Kim             key = capi_get_key(ctx, (TCHAR *)id,
15487bded2dbSJung-uk Kim                                (TCHAR *)ctx->cspname,
15497bded2dbSJung-uk Kim                                ctx->csptype, ctx->keytype);
1550db522d3aSSimon L. B. Nielsen         break;
1551db522d3aSSimon L. B. Nielsen     }
1552db522d3aSSimon L. B. Nielsen 
1553db522d3aSSimon L. B. Nielsen     return key;
1554db522d3aSSimon L. B. Nielsen }
1555db522d3aSSimon L. B. Nielsen 
1556db522d3aSSimon L. B. Nielsen void capi_free_key(CAPI_KEY * key)
1557db522d3aSSimon L. B. Nielsen {
1558db522d3aSSimon L. B. Nielsen     if (!key)
1559db522d3aSSimon L. B. Nielsen         return;
1560db522d3aSSimon L. B. Nielsen     CryptDestroyKey(key->key);
1561db522d3aSSimon L. B. Nielsen     CryptReleaseContext(key->hprov, 0);
1562db522d3aSSimon L. B. Nielsen     if (key->pcert)
1563db522d3aSSimon L. B. Nielsen         CertFreeCertificateContext(key->pcert);
1564db522d3aSSimon L. B. Nielsen     OPENSSL_free(key);
1565db522d3aSSimon L. B. Nielsen }
1566db522d3aSSimon L. B. Nielsen 
1567db522d3aSSimon L. B. Nielsen /* Initialize a CAPI_CTX structure */
1568db522d3aSSimon L. B. Nielsen 
1569db522d3aSSimon L. B. Nielsen static CAPI_CTX *capi_ctx_new()
1570db522d3aSSimon L. B. Nielsen {
1571db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
1572db522d3aSSimon L. B. Nielsen     ctx = OPENSSL_malloc(sizeof(CAPI_CTX));
15736f9291ceSJung-uk Kim     if (!ctx) {
1574db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_CTX_NEW, ERR_R_MALLOC_FAILURE);
1575db522d3aSSimon L. B. Nielsen         return NULL;
1576db522d3aSSimon L. B. Nielsen     }
1577db522d3aSSimon L. B. Nielsen     ctx->cspname = NULL;
1578db522d3aSSimon L. B. Nielsen     ctx->csptype = PROV_RSA_FULL;
1579db522d3aSSimon L. B. Nielsen     ctx->dump_flags = CAPI_DMP_SUMMARY | CAPI_DMP_FNAME;
1580db522d3aSSimon L. B. Nielsen     ctx->keytype = AT_KEYEXCHANGE;
1581db522d3aSSimon L. B. Nielsen     ctx->storename = NULL;
1582db522d3aSSimon L. B. Nielsen     ctx->ssl_client_store = NULL;
1583db522d3aSSimon L. B. Nielsen     ctx->store_flags = CERT_STORE_OPEN_EXISTING_FLAG |
15846f9291ceSJung-uk Kim         CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_CURRENT_USER;
1585db522d3aSSimon L. B. Nielsen     ctx->lookup_method = CAPI_LU_SUBSTR;
1586db522d3aSSimon L. B. Nielsen     ctx->debug_level = 0;
1587db522d3aSSimon L. B. Nielsen     ctx->debug_file = NULL;
1588db522d3aSSimon L. B. Nielsen     ctx->client_cert_select = cert_select_simple;
1589db522d3aSSimon L. B. Nielsen     return ctx;
1590db522d3aSSimon L. B. Nielsen }
1591db522d3aSSimon L. B. Nielsen 
1592db522d3aSSimon L. B. Nielsen static void capi_ctx_free(CAPI_CTX * ctx)
1593db522d3aSSimon L. B. Nielsen {
1594db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "Calling capi_ctx_free with %lx\n", ctx);
1595db522d3aSSimon L. B. Nielsen     if (!ctx)
1596db522d3aSSimon L. B. Nielsen         return;
1597db522d3aSSimon L. B. Nielsen     if (ctx->cspname)
1598db522d3aSSimon L. B. Nielsen         OPENSSL_free(ctx->cspname);
1599db522d3aSSimon L. B. Nielsen     if (ctx->debug_file)
1600db522d3aSSimon L. B. Nielsen         OPENSSL_free(ctx->debug_file);
1601db522d3aSSimon L. B. Nielsen     if (ctx->storename)
1602db522d3aSSimon L. B. Nielsen         OPENSSL_free(ctx->storename);
1603db522d3aSSimon L. B. Nielsen     if (ctx->ssl_client_store)
1604db522d3aSSimon L. B. Nielsen         OPENSSL_free(ctx->ssl_client_store);
1605db522d3aSSimon L. B. Nielsen     OPENSSL_free(ctx);
1606db522d3aSSimon L. B. Nielsen }
1607db522d3aSSimon L. B. Nielsen 
16086f9291ceSJung-uk Kim static int capi_ctx_set_provname(CAPI_CTX * ctx, LPSTR pname, DWORD type,
16096f9291ceSJung-uk Kim                                  int check)
1610db522d3aSSimon L. B. Nielsen {
1611db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "capi_ctx_set_provname, name=%s, type=%d\n", pname, type);
16126f9291ceSJung-uk Kim     if (check) {
1613db522d3aSSimon L. B. Nielsen         HCRYPTPROV hprov;
16147bded2dbSJung-uk Kim         LPTSTR name = NULL;
16157bded2dbSJung-uk Kim 
16167bded2dbSJung-uk Kim         if (sizeof(TCHAR) != sizeof(char)) {
16177bded2dbSJung-uk Kim             DWORD len;
16187bded2dbSJung-uk Kim             if ((len = MultiByteToWideChar(CP_ACP, 0, pname, -1, NULL, 0))) {
16197bded2dbSJung-uk Kim                 name = alloca(len * sizeof(WCHAR));
16207bded2dbSJung-uk Kim                 MultiByteToWideChar(CP_ACP, 0, pname, -1, (WCHAR *)name, len);
16217bded2dbSJung-uk Kim             }
16227bded2dbSJung-uk Kim         } else
16237bded2dbSJung-uk Kim             name = (TCHAR *)pname;
16247bded2dbSJung-uk Kim 
16257bded2dbSJung-uk Kim         if (!name || !CryptAcquireContext(&hprov, NULL, name, type,
16266f9291ceSJung-uk Kim                                           CRYPT_VERIFYCONTEXT)) {
16276f9291ceSJung-uk Kim             CAPIerr(CAPI_F_CAPI_CTX_SET_PROVNAME,
16286f9291ceSJung-uk Kim                     CAPI_R_CRYPTACQUIRECONTEXT_ERROR);
1629db522d3aSSimon L. B. Nielsen             capi_addlasterror();
1630db522d3aSSimon L. B. Nielsen             return 0;
1631db522d3aSSimon L. B. Nielsen         }
1632db522d3aSSimon L. B. Nielsen         CryptReleaseContext(hprov, 0);
1633db522d3aSSimon L. B. Nielsen     }
163412de4ed2SJung-uk Kim     if (ctx->cspname)
163512de4ed2SJung-uk Kim         OPENSSL_free(ctx->cspname);
1636db522d3aSSimon L. B. Nielsen     ctx->cspname = BUF_strdup(pname);
1637db522d3aSSimon L. B. Nielsen     ctx->csptype = type;
1638db522d3aSSimon L. B. Nielsen     return 1;
1639db522d3aSSimon L. B. Nielsen }
1640db522d3aSSimon L. B. Nielsen 
1641db522d3aSSimon L. B. Nielsen static int capi_ctx_set_provname_idx(CAPI_CTX * ctx, int idx)
1642db522d3aSSimon L. B. Nielsen {
1643db522d3aSSimon L. B. Nielsen     LPSTR pname;
1644db522d3aSSimon L. B. Nielsen     DWORD type;
164512de4ed2SJung-uk Kim     int res;
1646db522d3aSSimon L. B. Nielsen     if (capi_get_provname(ctx, &pname, &type, idx) != 1)
1647db522d3aSSimon L. B. Nielsen         return 0;
164812de4ed2SJung-uk Kim     res = capi_ctx_set_provname(ctx, pname, type, 0);
164912de4ed2SJung-uk Kim     OPENSSL_free(pname);
165012de4ed2SJung-uk Kim     return res;
1651db522d3aSSimon L. B. Nielsen }
1652db522d3aSSimon L. B. Nielsen 
1653db522d3aSSimon L. B. Nielsen static int cert_issuer_match(STACK_OF(X509_NAME) *ca_dn, X509 *x)
1654db522d3aSSimon L. B. Nielsen {
1655db522d3aSSimon L. B. Nielsen     int i;
1656db522d3aSSimon L. B. Nielsen     X509_NAME *nm;
1657db522d3aSSimon L. B. Nielsen     /* Special case: empty list: match anything */
1658db522d3aSSimon L. B. Nielsen     if (sk_X509_NAME_num(ca_dn) <= 0)
1659db522d3aSSimon L. B. Nielsen         return 1;
16606f9291ceSJung-uk Kim     for (i = 0; i < sk_X509_NAME_num(ca_dn); i++) {
1661db522d3aSSimon L. B. Nielsen         nm = sk_X509_NAME_value(ca_dn, i);
1662db522d3aSSimon L. B. Nielsen         if (!X509_NAME_cmp(nm, X509_get_issuer_name(x)))
1663db522d3aSSimon L. B. Nielsen             return 1;
1664db522d3aSSimon L. B. Nielsen     }
1665db522d3aSSimon L. B. Nielsen     return 0;
1666db522d3aSSimon L. B. Nielsen }
1667db522d3aSSimon L. B. Nielsen 
1668db522d3aSSimon L. B. Nielsen static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl,
16696f9291ceSJung-uk Kim                                      STACK_OF(X509_NAME) *ca_dn, X509 **pcert,
16706f9291ceSJung-uk Kim                                      EVP_PKEY **pkey, STACK_OF(X509) **pother,
16716f9291ceSJung-uk Kim                                      UI_METHOD *ui_method,
16726f9291ceSJung-uk Kim                                      void *callback_data)
1673db522d3aSSimon L. B. Nielsen {
1674db522d3aSSimon L. B. Nielsen     STACK_OF(X509) *certs = NULL;
1675db522d3aSSimon L. B. Nielsen     X509 *x;
1676db522d3aSSimon L. B. Nielsen     char *storename;
1677db522d3aSSimon L. B. Nielsen     const char *p;
1678db522d3aSSimon L. B. Nielsen     int i, client_cert_idx;
1679db522d3aSSimon L. B. Nielsen     HCERTSTORE hstore;
1680db522d3aSSimon L. B. Nielsen     PCCERT_CONTEXT cert = NULL, excert = NULL;
1681db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
1682db522d3aSSimon L. B. Nielsen     CAPI_KEY *key;
1683db522d3aSSimon L. B. Nielsen     ctx = ENGINE_get_ex_data(e, capi_idx);
1684db522d3aSSimon L. B. Nielsen 
1685db522d3aSSimon L. B. Nielsen     *pcert = NULL;
1686db522d3aSSimon L. B. Nielsen     *pkey = NULL;
1687db522d3aSSimon L. B. Nielsen 
1688db522d3aSSimon L. B. Nielsen     storename = ctx->ssl_client_store;
1689db522d3aSSimon L. B. Nielsen     if (!storename)
1690db522d3aSSimon L. B. Nielsen         storename = "MY";
1691db522d3aSSimon L. B. Nielsen 
1692db522d3aSSimon L. B. Nielsen     hstore = capi_open_store(ctx, storename);
1693db522d3aSSimon L. B. Nielsen     if (!hstore)
1694db522d3aSSimon L. B. Nielsen         return 0;
1695db522d3aSSimon L. B. Nielsen     /* Enumerate all certificates collect any matches */
16966f9291ceSJung-uk Kim     for (i = 0;; i++) {
1697db522d3aSSimon L. B. Nielsen         cert = CertEnumCertificatesInStore(hstore, cert);
1698db522d3aSSimon L. B. Nielsen         if (!cert)
1699db522d3aSSimon L. B. Nielsen             break;
1700db522d3aSSimon L. B. Nielsen         p = cert->pbCertEncoded;
1701db522d3aSSimon L. B. Nielsen         x = d2i_X509(NULL, &p, cert->cbCertEncoded);
17026f9291ceSJung-uk Kim         if (!x) {
1703db522d3aSSimon L. B. Nielsen             CAPI_trace(ctx, "Can't Parse Certificate %d\n", i);
1704db522d3aSSimon L. B. Nielsen             continue;
1705db522d3aSSimon L. B. Nielsen         }
1706db522d3aSSimon L. B. Nielsen         if (cert_issuer_match(ca_dn, x)
17076f9291ceSJung-uk Kim             && X509_check_purpose(x, X509_PURPOSE_SSL_CLIENT, 0)) {
1708db522d3aSSimon L. B. Nielsen             key = capi_get_cert_key(ctx, cert);
17096f9291ceSJung-uk Kim             if (!key) {
1710db522d3aSSimon L. B. Nielsen                 X509_free(x);
1711db522d3aSSimon L. B. Nielsen                 continue;
1712db522d3aSSimon L. B. Nielsen             }
17136f9291ceSJung-uk Kim             /*
17146f9291ceSJung-uk Kim              * Match found: attach extra data to it so we can retrieve the
17156f9291ceSJung-uk Kim              * key later.
1716db522d3aSSimon L. B. Nielsen              */
1717db522d3aSSimon L. B. Nielsen             excert = CertDuplicateCertificateContext(cert);
1718db522d3aSSimon L. B. Nielsen             key->pcert = excert;
1719db522d3aSSimon L. B. Nielsen             X509_set_ex_data(x, cert_capi_idx, key);
1720db522d3aSSimon L. B. Nielsen 
1721db522d3aSSimon L. B. Nielsen             if (!certs)
1722db522d3aSSimon L. B. Nielsen                 certs = sk_X509_new_null();
1723db522d3aSSimon L. B. Nielsen 
1724db522d3aSSimon L. B. Nielsen             sk_X509_push(certs, x);
17256f9291ceSJung-uk Kim         } else
1726db522d3aSSimon L. B. Nielsen             X509_free(x);
1727db522d3aSSimon L. B. Nielsen 
1728db522d3aSSimon L. B. Nielsen     }
1729db522d3aSSimon L. B. Nielsen 
1730db522d3aSSimon L. B. Nielsen     if (cert)
1731db522d3aSSimon L. B. Nielsen         CertFreeCertificateContext(cert);
1732db522d3aSSimon L. B. Nielsen     if (hstore)
1733db522d3aSSimon L. B. Nielsen         CertCloseStore(hstore, 0);
1734db522d3aSSimon L. B. Nielsen 
1735db522d3aSSimon L. B. Nielsen     if (!certs)
1736db522d3aSSimon L. B. Nielsen         return 0;
1737db522d3aSSimon L. B. Nielsen 
1738db522d3aSSimon L. B. Nielsen     /* Select the appropriate certificate */
1739db522d3aSSimon L. B. Nielsen 
1740db522d3aSSimon L. B. Nielsen     client_cert_idx = ctx->client_cert_select(e, ssl, certs);
1741db522d3aSSimon L. B. Nielsen 
1742db522d3aSSimon L. B. Nielsen     /* Set the selected certificate and free the rest */
1743db522d3aSSimon L. B. Nielsen 
17446f9291ceSJung-uk Kim     for (i = 0; i < sk_X509_num(certs); i++) {
1745db522d3aSSimon L. B. Nielsen         x = sk_X509_value(certs, i);
1746db522d3aSSimon L. B. Nielsen         if (i == client_cert_idx)
1747db522d3aSSimon L. B. Nielsen             *pcert = x;
17486f9291ceSJung-uk Kim         else {
1749db522d3aSSimon L. B. Nielsen             key = X509_get_ex_data(x, cert_capi_idx);
1750db522d3aSSimon L. B. Nielsen             capi_free_key(key);
1751db522d3aSSimon L. B. Nielsen             X509_free(x);
1752db522d3aSSimon L. B. Nielsen         }
1753db522d3aSSimon L. B. Nielsen     }
1754db522d3aSSimon L. B. Nielsen 
1755db522d3aSSimon L. B. Nielsen     sk_X509_free(certs);
1756db522d3aSSimon L. B. Nielsen 
1757db522d3aSSimon L. B. Nielsen     if (!*pcert)
1758db522d3aSSimon L. B. Nielsen         return 0;
1759db522d3aSSimon L. B. Nielsen 
1760db522d3aSSimon L. B. Nielsen     /* Setup key for selected certificate */
1761db522d3aSSimon L. B. Nielsen 
1762db522d3aSSimon L. B. Nielsen     key = X509_get_ex_data(*pcert, cert_capi_idx);
1763db522d3aSSimon L. B. Nielsen     *pkey = capi_get_pkey(e, key);
1764db522d3aSSimon L. B. Nielsen     X509_set_ex_data(*pcert, cert_capi_idx, NULL);
1765db522d3aSSimon L. B. Nielsen 
1766db522d3aSSimon L. B. Nielsen     return 1;
1767db522d3aSSimon L. B. Nielsen 
1768db522d3aSSimon L. B. Nielsen }
1769db522d3aSSimon L. B. Nielsen 
1770db522d3aSSimon L. B. Nielsen /* Simple client cert selection function: always select first */
1771db522d3aSSimon L. B. Nielsen 
1772db522d3aSSimon L. B. Nielsen static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs)
1773db522d3aSSimon L. B. Nielsen {
1774db522d3aSSimon L. B. Nielsen     return 0;
1775db522d3aSSimon L. B. Nielsen }
1776db522d3aSSimon L. B. Nielsen 
1777db522d3aSSimon L. B. Nielsen # ifdef OPENSSL_CAPIENG_DIALOG
1778db522d3aSSimon L. B. Nielsen 
17796f9291ceSJung-uk Kim /*
17806f9291ceSJung-uk Kim  * More complex cert selection function, using standard function
1781db522d3aSSimon L. B. Nielsen  * CryptUIDlgSelectCertificateFromStore() to produce a dialog box.
1782db522d3aSSimon L. B. Nielsen  */
1783db522d3aSSimon L. B. Nielsen 
17846f9291ceSJung-uk Kim /*
17856f9291ceSJung-uk Kim  * Definitions which are in cryptuiapi.h but this is not present in older
1786db522d3aSSimon L. B. Nielsen  * versions of headers.
1787db522d3aSSimon L. B. Nielsen  */
1788db522d3aSSimon L. B. Nielsen 
1789db522d3aSSimon L. B. Nielsen #  ifndef CRYPTUI_SELECT_LOCATION_COLUMN
1790db522d3aSSimon L. B. Nielsen #   define CRYPTUI_SELECT_LOCATION_COLUMN                   0x000000010
1791db522d3aSSimon L. B. Nielsen #   define CRYPTUI_SELECT_INTENDEDUSE_COLUMN                0x000000004
1792db522d3aSSimon L. B. Nielsen #  endif
1793db522d3aSSimon L. B. Nielsen 
1794db522d3aSSimon L. B. Nielsen #  define dlg_title L"OpenSSL Application SSL Client Certificate Selection"
1795db522d3aSSimon L. B. Nielsen #  define dlg_prompt L"Select a certificate to use for authentication"
1796db522d3aSSimon L. B. Nielsen #  define dlg_columns      CRYPTUI_SELECT_LOCATION_COLUMN \
1797db522d3aSSimon L. B. Nielsen                         |CRYPTUI_SELECT_INTENDEDUSE_COLUMN
1798db522d3aSSimon L. B. Nielsen 
1799db522d3aSSimon L. B. Nielsen static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs)
1800db522d3aSSimon L. B. Nielsen {
1801db522d3aSSimon L. B. Nielsen     X509 *x;
1802db522d3aSSimon L. B. Nielsen     HCERTSTORE dstore;
1803db522d3aSSimon L. B. Nielsen     PCCERT_CONTEXT cert;
1804db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
1805db522d3aSSimon L. B. Nielsen     CAPI_KEY *key;
1806db522d3aSSimon L. B. Nielsen     HWND hwnd;
1807db522d3aSSimon L. B. Nielsen     int i, idx = -1;
1808db522d3aSSimon L. B. Nielsen     if (sk_X509_num(certs) == 1)
1809db522d3aSSimon L. B. Nielsen         return 0;
1810db522d3aSSimon L. B. Nielsen     ctx = ENGINE_get_ex_data(e, capi_idx);
1811db522d3aSSimon L. B. Nielsen     /* Create an in memory store of certificates */
1812db522d3aSSimon L. B. Nielsen     dstore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1813db522d3aSSimon L. B. Nielsen                            CERT_STORE_CREATE_NEW_FLAG, NULL);
18146f9291ceSJung-uk Kim     if (!dstore) {
1815db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_CREATING_STORE);
1816db522d3aSSimon L. B. Nielsen         capi_addlasterror();
1817db522d3aSSimon L. B. Nielsen         goto err;
1818db522d3aSSimon L. B. Nielsen     }
1819db522d3aSSimon L. B. Nielsen     /* Add all certificates to store */
18206f9291ceSJung-uk Kim     for (i = 0; i < sk_X509_num(certs); i++) {
1821db522d3aSSimon L. B. Nielsen         x = sk_X509_value(certs, i);
1822db522d3aSSimon L. B. Nielsen         key = X509_get_ex_data(x, cert_capi_idx);
1823db522d3aSSimon L. B. Nielsen 
1824db522d3aSSimon L. B. Nielsen         if (!CertAddCertificateContextToStore(dstore, key->pcert,
18256f9291ceSJung-uk Kim                                               CERT_STORE_ADD_NEW, NULL)) {
1826db522d3aSSimon L. B. Nielsen             CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_ADDING_CERT);
1827db522d3aSSimon L. B. Nielsen             capi_addlasterror();
1828db522d3aSSimon L. B. Nielsen             goto err;
1829db522d3aSSimon L. B. Nielsen         }
1830db522d3aSSimon L. B. Nielsen 
1831db522d3aSSimon L. B. Nielsen     }
1832db522d3aSSimon L. B. Nielsen     hwnd = GetForegroundWindow();
1833db522d3aSSimon L. B. Nielsen     if (!hwnd)
1834db522d3aSSimon L. B. Nielsen         hwnd = GetActiveWindow();
1835db522d3aSSimon L. B. Nielsen     if (!hwnd && ctx->getconswindow)
1836db522d3aSSimon L. B. Nielsen         hwnd = ctx->getconswindow();
1837db522d3aSSimon L. B. Nielsen     /* Call dialog to select one */
1838db522d3aSSimon L. B. Nielsen     cert = ctx->certselectdlg(dstore, hwnd, dlg_title, dlg_prompt,
1839db522d3aSSimon L. B. Nielsen                               dlg_columns, 0, NULL);
1840db522d3aSSimon L. B. Nielsen 
1841db522d3aSSimon L. B. Nielsen     /* Find matching cert from list */
18426f9291ceSJung-uk Kim     if (cert) {
18436f9291ceSJung-uk Kim         for (i = 0; i < sk_X509_num(certs); i++) {
1844db522d3aSSimon L. B. Nielsen             x = sk_X509_value(certs, i);
1845db522d3aSSimon L. B. Nielsen             key = X509_get_ex_data(x, cert_capi_idx);
18466f9291ceSJung-uk Kim             if (CertCompareCertificate
18476f9291ceSJung-uk Kim                 (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, cert->pCertInfo,
18486f9291ceSJung-uk Kim                  key->pcert->pCertInfo)) {
1849db522d3aSSimon L. B. Nielsen                 idx = i;
1850db522d3aSSimon L. B. Nielsen                 break;
1851db522d3aSSimon L. B. Nielsen             }
1852db522d3aSSimon L. B. Nielsen         }
1853db522d3aSSimon L. B. Nielsen     }
1854db522d3aSSimon L. B. Nielsen 
1855db522d3aSSimon L. B. Nielsen  err:
1856db522d3aSSimon L. B. Nielsen     if (dstore)
1857db522d3aSSimon L. B. Nielsen         CertCloseStore(dstore, 0);
1858db522d3aSSimon L. B. Nielsen     return idx;
1859db522d3aSSimon L. B. Nielsen 
1860db522d3aSSimon L. B. Nielsen }
1861db522d3aSSimon L. B. Nielsen # endif
1862db522d3aSSimon L. B. Nielsen 
18631f13597dSJung-uk Kim #else                           /* !__COMPILE_CAPIENG */
1864db522d3aSSimon L. B. Nielsen # include <openssl/engine.h>
1865db522d3aSSimon L. B. Nielsen # ifndef OPENSSL_NO_DYNAMIC_ENGINE
1866db522d3aSSimon L. B. Nielsen OPENSSL_EXPORT
18671f13597dSJung-uk Kim     int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns);
18681f13597dSJung-uk Kim OPENSSL_EXPORT
18696f9291ceSJung-uk Kim     int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns)
18706f9291ceSJung-uk Kim {
18716f9291ceSJung-uk Kim     return 0;
18726f9291ceSJung-uk Kim }
18736f9291ceSJung-uk Kim 
1874db522d3aSSimon L. B. Nielsen IMPLEMENT_DYNAMIC_CHECK_FN()
18751f13597dSJung-uk Kim # else
18766f9291ceSJung-uk Kim void ENGINE_load_capi(void)
18776f9291ceSJung-uk Kim {
18786f9291ceSJung-uk Kim }
1879db522d3aSSimon L. B. Nielsen # endif
1880db522d3aSSimon L. B. Nielsen #endif
1881