xref: /freebsd/crypto/openssl/engines/e_capi.c (revision b077aed33b7b6aefca7b17ddb250cf521f938613)
16f9291ceSJung-uk Kim /*
2*b077aed3SPierre Pronchery  * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
3e71b7053SJung-uk Kim  *
4*b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5e71b7053SJung-uk Kim  * this file except in compliance with the License.  You can obtain a copy
6e71b7053SJung-uk Kim  * in the file LICENSE in the source distribution or at
7e71b7053SJung-uk Kim  * https://www.openssl.org/source/license.html
8db522d3aSSimon L. B. Nielsen  */
9e71b7053SJung-uk Kim 
10*b077aed3SPierre Pronchery /* We need to use some deprecated APIs */
11*b077aed3SPierre Pronchery #define OPENSSL_SUPPRESS_DEPRECATED
12*b077aed3SPierre Pronchery 
13e71b7053SJung-uk Kim #ifdef _WIN32
14e71b7053SJung-uk Kim # ifndef _WIN32_WINNT
15e71b7053SJung-uk Kim #  define _WIN32_WINNT 0x0400
16e71b7053SJung-uk Kim # endif
17e71b7053SJung-uk Kim # include <windows.h>
18e71b7053SJung-uk Kim # include <wincrypt.h>
19db522d3aSSimon L. B. Nielsen 
20db522d3aSSimon L. B. Nielsen # include <stdio.h>
21db522d3aSSimon L. B. Nielsen # include <string.h>
227bded2dbSJung-uk Kim # include <stdlib.h>
23e71b7053SJung-uk Kim # include <malloc.h>
24e71b7053SJung-uk Kim # ifndef alloca
25e71b7053SJung-uk Kim #  define alloca _alloca
26e71b7053SJung-uk Kim # endif
277bded2dbSJung-uk Kim 
28db522d3aSSimon L. B. Nielsen # include <openssl/crypto.h>
29db522d3aSSimon L. B. Nielsen 
30db522d3aSSimon L. B. Nielsen # ifndef OPENSSL_NO_CAPIENG
31db522d3aSSimon L. B. Nielsen 
327bded2dbSJung-uk Kim #  include <openssl/buffer.h>
337bded2dbSJung-uk Kim #  include <openssl/bn.h>
346a599222SSimon L. B. Nielsen #  include <openssl/rsa.h>
35e71b7053SJung-uk Kim #  include <openssl/dsa.h>
36db522d3aSSimon L. B. Nielsen 
371f13597dSJung-uk Kim /*
381f13597dSJung-uk Kim  * This module uses several "new" interfaces, among which is
391f13597dSJung-uk Kim  * CertGetCertificateContextProperty. CERT_KEY_PROV_INFO_PROP_ID is
401f13597dSJung-uk Kim  * one of possible values you can pass to function in question. By
411f13597dSJung-uk Kim  * checking if it's defined we can see if wincrypt.h and accompanying
421f13597dSJung-uk Kim  * crypt32.lib are in shape. The native MingW32 headers up to and
431f13597dSJung-uk Kim  * including __W32API_VERSION 3.14 lack of struct DSSPUBKEY and the
441f13597dSJung-uk Kim  * defines CERT_STORE_PROV_SYSTEM_A and CERT_STORE_READONLY_FLAG,
451f13597dSJung-uk Kim  * so we check for these too and avoid compiling.
461f13597dSJung-uk Kim  * Yes, it's rather "weak" test and if compilation fails,
471f13597dSJung-uk Kim  * then re-configure with -DOPENSSL_NO_CAPIENG.
481f13597dSJung-uk Kim  */
491f13597dSJung-uk Kim #  if defined(CERT_KEY_PROV_INFO_PROP_ID) && \
501f13597dSJung-uk Kim     defined(CERT_STORE_PROV_SYSTEM_A) && \
511f13597dSJung-uk Kim     defined(CERT_STORE_READONLY_FLAG)
521f13597dSJung-uk Kim #   define __COMPILE_CAPIENG
531f13597dSJung-uk Kim #  endif                        /* CERT_KEY_PROV_INFO_PROP_ID */
541f13597dSJung-uk Kim # endif                         /* OPENSSL_NO_CAPIENG */
55e71b7053SJung-uk Kim #endif                          /* _WIN32 */
561f13597dSJung-uk Kim 
571f13597dSJung-uk Kim #ifdef __COMPILE_CAPIENG
581f13597dSJung-uk Kim 
59db522d3aSSimon L. B. Nielsen # undef X509_EXTENSIONS
60db522d3aSSimon L. B. Nielsen 
61db522d3aSSimon L. B. Nielsen /* Definitions which may be missing from earlier version of headers */
62db522d3aSSimon L. B. Nielsen # ifndef CERT_STORE_OPEN_EXISTING_FLAG
63db522d3aSSimon L. B. Nielsen #  define CERT_STORE_OPEN_EXISTING_FLAG                   0x00004000
64db522d3aSSimon L. B. Nielsen # endif
65db522d3aSSimon L. B. Nielsen 
66db522d3aSSimon L. B. Nielsen # ifndef CERT_STORE_CREATE_NEW_FLAG
67db522d3aSSimon L. B. Nielsen #  define CERT_STORE_CREATE_NEW_FLAG                      0x00002000
68db522d3aSSimon L. B. Nielsen # endif
69db522d3aSSimon L. B. Nielsen 
70ab8565e2SSimon L. B. Nielsen # ifndef CERT_SYSTEM_STORE_CURRENT_USER
71ab8565e2SSimon L. B. Nielsen #  define CERT_SYSTEM_STORE_CURRENT_USER                  0x00010000
72ab8565e2SSimon L. B. Nielsen # endif
73ab8565e2SSimon L. B. Nielsen 
744c6a0400SJung-uk Kim # ifndef ALG_SID_SHA_256
754c6a0400SJung-uk Kim #  define ALG_SID_SHA_256   12
764c6a0400SJung-uk Kim # endif
774c6a0400SJung-uk Kim # ifndef ALG_SID_SHA_384
784c6a0400SJung-uk Kim #  define ALG_SID_SHA_384   13
794c6a0400SJung-uk Kim # endif
804c6a0400SJung-uk Kim # ifndef ALG_SID_SHA_512
814c6a0400SJung-uk Kim #  define ALG_SID_SHA_512   14
824c6a0400SJung-uk Kim # endif
834c6a0400SJung-uk Kim 
844c6a0400SJung-uk Kim # ifndef CALG_SHA_256
854c6a0400SJung-uk Kim #  define CALG_SHA_256      (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_256)
864c6a0400SJung-uk Kim # endif
874c6a0400SJung-uk Kim # ifndef CALG_SHA_384
884c6a0400SJung-uk Kim #  define CALG_SHA_384      (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_384)
894c6a0400SJung-uk Kim # endif
904c6a0400SJung-uk Kim # ifndef CALG_SHA_512
914c6a0400SJung-uk Kim #  define CALG_SHA_512      (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_512)
924c6a0400SJung-uk Kim # endif
934c6a0400SJung-uk Kim 
94e71b7053SJung-uk Kim # ifndef PROV_RSA_AES
95e71b7053SJung-uk Kim #  define PROV_RSA_AES 24
96e71b7053SJung-uk Kim # endif
97e71b7053SJung-uk Kim 
98db522d3aSSimon L. B. Nielsen # include <openssl/engine.h>
99db522d3aSSimon L. B. Nielsen # include <openssl/pem.h>
100db522d3aSSimon L. B. Nielsen # include <openssl/x509v3.h>
101db522d3aSSimon L. B. Nielsen 
102db522d3aSSimon L. B. Nielsen # include "e_capi_err.h"
103db522d3aSSimon L. B. Nielsen # include "e_capi_err.c"
104db522d3aSSimon L. B. Nielsen 
105db522d3aSSimon L. B. Nielsen static const char *engine_capi_id = "capi";
106db522d3aSSimon L. B. Nielsen static const char *engine_capi_name = "CryptoAPI ENGINE";
107db522d3aSSimon L. B. Nielsen 
108db522d3aSSimon L. B. Nielsen typedef struct CAPI_CTX_st CAPI_CTX;
109db522d3aSSimon L. B. Nielsen typedef struct CAPI_KEY_st CAPI_KEY;
110db522d3aSSimon L. B. Nielsen 
111db522d3aSSimon L. B. Nielsen static void capi_addlasterror(void);
112db522d3aSSimon L. B. Nielsen static void capi_adderror(DWORD err);
113db522d3aSSimon L. B. Nielsen 
114db522d3aSSimon L. B. Nielsen static void CAPI_trace(CAPI_CTX *ctx, char *format, ...);
115db522d3aSSimon L. B. Nielsen 
116db522d3aSSimon L. B. Nielsen static int capi_list_providers(CAPI_CTX *ctx, BIO *out);
117db522d3aSSimon L. B. Nielsen static int capi_list_containers(CAPI_CTX *ctx, BIO *out);
118db522d3aSSimon L. B. Nielsen int capi_list_certs(CAPI_CTX *ctx, BIO *out, char *storename);
119db522d3aSSimon L. B. Nielsen void capi_free_key(CAPI_KEY *key);
120db522d3aSSimon L. B. Nielsen 
1216f9291ceSJung-uk Kim static PCCERT_CONTEXT capi_find_cert(CAPI_CTX *ctx, const char *id,
1226f9291ceSJung-uk Kim                                      HCERTSTORE hstore);
123db522d3aSSimon L. B. Nielsen 
124db522d3aSSimon L. B. Nielsen CAPI_KEY *capi_find_key(CAPI_CTX *ctx, const char *id);
125db522d3aSSimon L. B. Nielsen 
126db522d3aSSimon L. B. Nielsen static EVP_PKEY *capi_load_privkey(ENGINE *eng, const char *key_id,
127db522d3aSSimon L. B. Nielsen                                    UI_METHOD *ui_method, void *callback_data);
1286f9291ceSJung-uk Kim static int capi_rsa_sign(int dtype, const unsigned char *m,
1296f9291ceSJung-uk Kim                          unsigned int m_len, unsigned char *sigret,
1306f9291ceSJung-uk Kim                          unsigned int *siglen, const RSA *rsa);
131db522d3aSSimon L. B. Nielsen static int capi_rsa_priv_enc(int flen, const unsigned char *from,
132db522d3aSSimon L. B. Nielsen                              unsigned char *to, RSA *rsa, int padding);
133db522d3aSSimon L. B. Nielsen static int capi_rsa_priv_dec(int flen, const unsigned char *from,
134db522d3aSSimon L. B. Nielsen                              unsigned char *to, RSA *rsa, int padding);
135db522d3aSSimon L. B. Nielsen static int capi_rsa_free(RSA *rsa);
136db522d3aSSimon L. B. Nielsen 
137e71b7053SJung-uk Kim # ifndef OPENSSL_NO_DSA
138db522d3aSSimon L. B. Nielsen static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen,
139db522d3aSSimon L. B. Nielsen                                  DSA *dsa);
140db522d3aSSimon L. B. Nielsen static int capi_dsa_free(DSA *dsa);
141e71b7053SJung-uk Kim # endif
142db522d3aSSimon L. B. Nielsen 
143db522d3aSSimon L. B. Nielsen static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl,
1446f9291ceSJung-uk Kim                                      STACK_OF(X509_NAME) *ca_dn, X509 **pcert,
1456f9291ceSJung-uk Kim                                      EVP_PKEY **pkey, STACK_OF(X509) **pother,
1466f9291ceSJung-uk Kim                                      UI_METHOD *ui_method,
1476f9291ceSJung-uk Kim                                      void *callback_data);
148db522d3aSSimon L. B. Nielsen 
149db522d3aSSimon L. B. Nielsen static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
150db522d3aSSimon L. B. Nielsen # ifdef OPENSSL_CAPIENG_DIALOG
151db522d3aSSimon L. B. Nielsen static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
152db522d3aSSimon L. B. Nielsen # endif
153db522d3aSSimon L. B. Nielsen 
154e71b7053SJung-uk Kim void engine_load_capi_int(void);
155e71b7053SJung-uk Kim 
156db522d3aSSimon L. B. Nielsen typedef PCCERT_CONTEXT(WINAPI *CERTDLG)(HCERTSTORE, HWND, LPCWSTR,
1576f9291ceSJung-uk Kim                                         LPCWSTR, DWORD, DWORD, void *);
158db522d3aSSimon L. B. Nielsen typedef HWND(WINAPI *GETCONSWIN)(void);
159db522d3aSSimon L. B. Nielsen 
1606f9291ceSJung-uk Kim /*
1616f9291ceSJung-uk Kim  * This structure contains CAPI ENGINE specific data: it contains various
1626f9291ceSJung-uk Kim  * global options and affects how other functions behave.
163db522d3aSSimon L. B. Nielsen  */
164db522d3aSSimon L. B. Nielsen 
165db522d3aSSimon L. B. Nielsen # define CAPI_DBG_TRACE  2
166db522d3aSSimon L. B. Nielsen # define CAPI_DBG_ERROR  1
167db522d3aSSimon L. B. Nielsen 
168db522d3aSSimon L. B. Nielsen struct CAPI_CTX_st {
169db522d3aSSimon L. B. Nielsen     int debug_level;
170db522d3aSSimon L. B. Nielsen     char *debug_file;
171db522d3aSSimon L. B. Nielsen     /* Parameters to use for container lookup */
172db522d3aSSimon L. B. Nielsen     DWORD keytype;
1736a599222SSimon L. B. Nielsen     LPSTR cspname;
174db522d3aSSimon L. B. Nielsen     DWORD csptype;
175db522d3aSSimon L. B. Nielsen     /* Certificate store name to use */
1766a599222SSimon L. B. Nielsen     LPSTR storename;
1776a599222SSimon L. B. Nielsen     LPSTR ssl_client_store;
178db522d3aSSimon L. B. Nielsen     /* System store flags */
179db522d3aSSimon L. B. Nielsen     DWORD store_flags;
180db522d3aSSimon L. B. Nielsen /* Lookup string meanings in load_private_key */
181e71b7053SJung-uk Kim # define CAPI_LU_SUBSTR          1  /* Substring of subject: uses "storename" */
182e71b7053SJung-uk Kim # define CAPI_LU_FNAME           2  /* Friendly name: uses storename */
183e71b7053SJung-uk Kim # define CAPI_LU_CONTNAME        3  /* Container name: uses cspname, keytype */
184db522d3aSSimon L. B. Nielsen     int lookup_method;
185db522d3aSSimon L. B. Nielsen /* Info to dump with dumpcerts option */
186e71b7053SJung-uk Kim # define CAPI_DMP_SUMMARY        0x1    /* Issuer and serial name strings */
187e71b7053SJung-uk Kim # define CAPI_DMP_FNAME          0x2    /* Friendly name */
188e71b7053SJung-uk Kim # define CAPI_DMP_FULL           0x4    /* Full X509_print dump */
189e71b7053SJung-uk Kim # define CAPI_DMP_PEM            0x8    /* Dump PEM format certificate */
190e71b7053SJung-uk Kim # define CAPI_DMP_PSKEY          0x10   /* Dump pseudo key (if possible) */
191e71b7053SJung-uk Kim # define CAPI_DMP_PKEYINFO       0x20   /* Dump key info (if possible) */
192db522d3aSSimon L. B. Nielsen     DWORD dump_flags;
193db522d3aSSimon L. B. Nielsen     int (*client_cert_select) (ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
194db522d3aSSimon L. B. Nielsen     CERTDLG certselectdlg;
195db522d3aSSimon L. B. Nielsen     GETCONSWIN getconswindow;
196db522d3aSSimon L. B. Nielsen };
197db522d3aSSimon L. B. Nielsen 
198e71b7053SJung-uk Kim static CAPI_CTX *capi_ctx_new(void);
199db522d3aSSimon L. B. Nielsen static void capi_ctx_free(CAPI_CTX *ctx);
2006f9291ceSJung-uk Kim static int capi_ctx_set_provname(CAPI_CTX *ctx, LPSTR pname, DWORD type,
2016f9291ceSJung-uk Kim                                  int check);
202db522d3aSSimon L. B. Nielsen static int capi_ctx_set_provname_idx(CAPI_CTX *ctx, int idx);
203db522d3aSSimon L. B. Nielsen 
204db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LIST_CERTS             ENGINE_CMD_BASE
205db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LOOKUP_CERT            (ENGINE_CMD_BASE + 1)
206db522d3aSSimon L. B. Nielsen # define CAPI_CMD_DEBUG_LEVEL            (ENGINE_CMD_BASE + 2)
207db522d3aSSimon L. B. Nielsen # define CAPI_CMD_DEBUG_FILE             (ENGINE_CMD_BASE + 3)
208db522d3aSSimon L. B. Nielsen # define CAPI_CMD_KEYTYPE                (ENGINE_CMD_BASE + 4)
209db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LIST_CSPS              (ENGINE_CMD_BASE + 5)
210db522d3aSSimon L. B. Nielsen # define CAPI_CMD_SET_CSP_IDX            (ENGINE_CMD_BASE + 6)
211db522d3aSSimon L. B. Nielsen # define CAPI_CMD_SET_CSP_NAME           (ENGINE_CMD_BASE + 7)
212db522d3aSSimon L. B. Nielsen # define CAPI_CMD_SET_CSP_TYPE           (ENGINE_CMD_BASE + 8)
213db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LIST_CONTAINERS        (ENGINE_CMD_BASE + 9)
214db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LIST_OPTIONS           (ENGINE_CMD_BASE + 10)
215db522d3aSSimon L. B. Nielsen # define CAPI_CMD_LOOKUP_METHOD          (ENGINE_CMD_BASE + 11)
216db522d3aSSimon L. B. Nielsen # define CAPI_CMD_STORE_NAME             (ENGINE_CMD_BASE + 12)
217db522d3aSSimon L. B. Nielsen # define CAPI_CMD_STORE_FLAGS            (ENGINE_CMD_BASE + 13)
218db522d3aSSimon L. B. Nielsen 
219db522d3aSSimon L. B. Nielsen static const ENGINE_CMD_DEFN capi_cmd_defns[] = {
220db522d3aSSimon L. B. Nielsen     {CAPI_CMD_LIST_CERTS,
221db522d3aSSimon L. B. Nielsen      "list_certs",
222db522d3aSSimon L. B. Nielsen      "List all certificates in store",
223db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NO_INPUT},
224db522d3aSSimon L. B. Nielsen     {CAPI_CMD_LOOKUP_CERT,
225db522d3aSSimon L. B. Nielsen      "lookup_cert",
226db522d3aSSimon L. B. Nielsen      "Lookup and output certificates",
227db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_STRING},
228db522d3aSSimon L. B. Nielsen     {CAPI_CMD_DEBUG_LEVEL,
229db522d3aSSimon L. B. Nielsen      "debug_level",
230db522d3aSSimon L. B. Nielsen      "debug level (1=errors, 2=trace)",
231db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NUMERIC},
232db522d3aSSimon L. B. Nielsen     {CAPI_CMD_DEBUG_FILE,
233db522d3aSSimon L. B. Nielsen      "debug_file",
234db522d3aSSimon L. B. Nielsen      "debugging filename)",
235db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_STRING},
236db522d3aSSimon L. B. Nielsen     {CAPI_CMD_KEYTYPE,
237db522d3aSSimon L. B. Nielsen      "key_type",
238db522d3aSSimon L. B. Nielsen      "Key type: 1=AT_KEYEXCHANGE (default), 2=AT_SIGNATURE",
239db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NUMERIC},
240db522d3aSSimon L. B. Nielsen     {CAPI_CMD_LIST_CSPS,
241db522d3aSSimon L. B. Nielsen      "list_csps",
242db522d3aSSimon L. B. Nielsen      "List all CSPs",
243db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NO_INPUT},
244db522d3aSSimon L. B. Nielsen     {CAPI_CMD_SET_CSP_IDX,
245db522d3aSSimon L. B. Nielsen      "csp_idx",
246db522d3aSSimon L. B. Nielsen      "Set CSP by index",
247db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NUMERIC},
248db522d3aSSimon L. B. Nielsen     {CAPI_CMD_SET_CSP_NAME,
249db522d3aSSimon L. B. Nielsen      "csp_name",
250db522d3aSSimon L. B. Nielsen      "Set CSP name, (default CSP used if not specified)",
251db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_STRING},
252db522d3aSSimon L. B. Nielsen     {CAPI_CMD_SET_CSP_TYPE,
253db522d3aSSimon L. B. Nielsen      "csp_type",
254db522d3aSSimon L. B. Nielsen      "Set CSP type, (default RSA_PROV_FULL)",
255db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NUMERIC},
256db522d3aSSimon L. B. Nielsen     {CAPI_CMD_LIST_CONTAINERS,
257db522d3aSSimon L. B. Nielsen      "list_containers",
258db522d3aSSimon L. B. Nielsen      "list container names",
259db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NO_INPUT},
260db522d3aSSimon L. B. Nielsen     {CAPI_CMD_LIST_OPTIONS,
261db522d3aSSimon L. B. Nielsen      "list_options",
262db522d3aSSimon L. B. Nielsen      "Set list options (1=summary,2=friendly name, 4=full printout, 8=PEM output, 16=XXX, "
263db522d3aSSimon L. B. Nielsen      "32=private key info)",
264db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NUMERIC},
265db522d3aSSimon L. B. Nielsen     {CAPI_CMD_LOOKUP_METHOD,
266db522d3aSSimon L. B. Nielsen      "lookup_method",
267db522d3aSSimon L. B. Nielsen      "Set key lookup method (1=substring, 2=friendlyname, 3=container name)",
268db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NUMERIC},
269db522d3aSSimon L. B. Nielsen     {CAPI_CMD_STORE_NAME,
270db522d3aSSimon L. B. Nielsen      "store_name",
271db522d3aSSimon L. B. Nielsen      "certificate store name, default \"MY\"",
272db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_STRING},
273db522d3aSSimon L. B. Nielsen     {CAPI_CMD_STORE_FLAGS,
274db522d3aSSimon L. B. Nielsen      "store_flags",
275db522d3aSSimon L. B. Nielsen      "Certificate store flags: 1 = system store",
276db522d3aSSimon L. B. Nielsen      ENGINE_CMD_FLAG_NUMERIC},
277db522d3aSSimon L. B. Nielsen 
278db522d3aSSimon L. B. Nielsen     {0, NULL, NULL, 0}
279db522d3aSSimon L. B. Nielsen };
280db522d3aSSimon L. B. Nielsen 
281db522d3aSSimon L. B. Nielsen static int capi_idx = -1;
282db522d3aSSimon L. B. Nielsen static int rsa_capi_idx = -1;
283db522d3aSSimon L. B. Nielsen static int dsa_capi_idx = -1;
284db522d3aSSimon L. B. Nielsen static int cert_capi_idx = -1;
285db522d3aSSimon L. B. Nielsen 
capi_ctrl(ENGINE * e,int cmd,long i,void * p,void (* f)(void))286db522d3aSSimon L. B. Nielsen static int capi_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
287db522d3aSSimon L. B. Nielsen {
288db522d3aSSimon L. B. Nielsen     int ret = 1;
289db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
290db522d3aSSimon L. B. Nielsen     BIO *out;
291e71b7053SJung-uk Kim     LPSTR tmpstr;
2926f9291ceSJung-uk Kim     if (capi_idx == -1) {
293db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_ENGINE_NOT_INITIALIZED);
294db522d3aSSimon L. B. Nielsen         return 0;
295db522d3aSSimon L. B. Nielsen     }
296db522d3aSSimon L. B. Nielsen     ctx = ENGINE_get_ex_data(e, capi_idx);
297db522d3aSSimon L. B. Nielsen     out = BIO_new_fp(stdout, BIO_NOCLOSE);
298e71b7053SJung-uk Kim     if (out == NULL) {
299e71b7053SJung-uk Kim         CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_FILE_OPEN_ERROR);
300e71b7053SJung-uk Kim         return 0;
301e71b7053SJung-uk Kim     }
3026f9291ceSJung-uk Kim     switch (cmd) {
303db522d3aSSimon L. B. Nielsen     case CAPI_CMD_LIST_CSPS:
304db522d3aSSimon L. B. Nielsen         ret = capi_list_providers(ctx, out);
305db522d3aSSimon L. B. Nielsen         break;
306db522d3aSSimon L. B. Nielsen 
307db522d3aSSimon L. B. Nielsen     case CAPI_CMD_LIST_CERTS:
308db522d3aSSimon L. B. Nielsen         ret = capi_list_certs(ctx, out, NULL);
309db522d3aSSimon L. B. Nielsen         break;
310db522d3aSSimon L. B. Nielsen 
311db522d3aSSimon L. B. Nielsen     case CAPI_CMD_LOOKUP_CERT:
312db522d3aSSimon L. B. Nielsen         ret = capi_list_certs(ctx, out, p);
313db522d3aSSimon L. B. Nielsen         break;
314db522d3aSSimon L. B. Nielsen 
315db522d3aSSimon L. B. Nielsen     case CAPI_CMD_LIST_CONTAINERS:
316db522d3aSSimon L. B. Nielsen         ret = capi_list_containers(ctx, out);
317db522d3aSSimon L. B. Nielsen         break;
318db522d3aSSimon L. B. Nielsen 
319db522d3aSSimon L. B. Nielsen     case CAPI_CMD_STORE_NAME:
320e71b7053SJung-uk Kim         tmpstr = OPENSSL_strdup(p);
321e71b7053SJung-uk Kim         if (tmpstr != NULL) {
322db522d3aSSimon L. B. Nielsen             OPENSSL_free(ctx->storename);
323e71b7053SJung-uk Kim             ctx->storename = tmpstr;
324db522d3aSSimon L. B. Nielsen             CAPI_trace(ctx, "Setting store name to %s\n", p);
325e71b7053SJung-uk Kim         } else {
326e71b7053SJung-uk Kim             CAPIerr(CAPI_F_CAPI_CTRL, ERR_R_MALLOC_FAILURE);
327e71b7053SJung-uk Kim             ret = 0;
328e71b7053SJung-uk Kim         }
329db522d3aSSimon L. B. Nielsen         break;
330db522d3aSSimon L. B. Nielsen 
331db522d3aSSimon L. B. Nielsen     case CAPI_CMD_STORE_FLAGS:
3326f9291ceSJung-uk Kim         if (i & 1) {
333db522d3aSSimon L. B. Nielsen             ctx->store_flags |= CERT_SYSTEM_STORE_LOCAL_MACHINE;
334db522d3aSSimon L. B. Nielsen             ctx->store_flags &= ~CERT_SYSTEM_STORE_CURRENT_USER;
3356f9291ceSJung-uk Kim         } else {
336db522d3aSSimon L. B. Nielsen             ctx->store_flags |= CERT_SYSTEM_STORE_CURRENT_USER;
337db522d3aSSimon L. B. Nielsen             ctx->store_flags &= ~CERT_SYSTEM_STORE_LOCAL_MACHINE;
338db522d3aSSimon L. B. Nielsen         }
339db522d3aSSimon L. B. Nielsen         CAPI_trace(ctx, "Setting flags to %d\n", i);
340db522d3aSSimon L. B. Nielsen         break;
341db522d3aSSimon L. B. Nielsen 
342db522d3aSSimon L. B. Nielsen     case CAPI_CMD_DEBUG_LEVEL:
343db522d3aSSimon L. B. Nielsen         ctx->debug_level = (int)i;
344db522d3aSSimon L. B. Nielsen         CAPI_trace(ctx, "Setting debug level to %d\n", ctx->debug_level);
345db522d3aSSimon L. B. Nielsen         break;
346db522d3aSSimon L. B. Nielsen 
347db522d3aSSimon L. B. Nielsen     case CAPI_CMD_DEBUG_FILE:
348e71b7053SJung-uk Kim         tmpstr = OPENSSL_strdup(p);
349e71b7053SJung-uk Kim         if (tmpstr != NULL) {
350e71b7053SJung-uk Kim             ctx->debug_file = tmpstr;
351db522d3aSSimon L. B. Nielsen             CAPI_trace(ctx, "Setting debug file to %s\n", ctx->debug_file);
352e71b7053SJung-uk Kim         } else {
353e71b7053SJung-uk Kim             CAPIerr(CAPI_F_CAPI_CTRL, ERR_R_MALLOC_FAILURE);
354e71b7053SJung-uk Kim             ret = 0;
355e71b7053SJung-uk Kim         }
356db522d3aSSimon L. B. Nielsen         break;
357db522d3aSSimon L. B. Nielsen 
358db522d3aSSimon L. B. Nielsen     case CAPI_CMD_KEYTYPE:
359db522d3aSSimon L. B. Nielsen         ctx->keytype = i;
360db522d3aSSimon L. B. Nielsen         CAPI_trace(ctx, "Setting key type to %d\n", ctx->keytype);
361db522d3aSSimon L. B. Nielsen         break;
362db522d3aSSimon L. B. Nielsen 
363db522d3aSSimon L. B. Nielsen     case CAPI_CMD_SET_CSP_IDX:
364db522d3aSSimon L. B. Nielsen         ret = capi_ctx_set_provname_idx(ctx, i);
365db522d3aSSimon L. B. Nielsen         break;
366db522d3aSSimon L. B. Nielsen 
367db522d3aSSimon L. B. Nielsen     case CAPI_CMD_LIST_OPTIONS:
368db522d3aSSimon L. B. Nielsen         ctx->dump_flags = i;
369db522d3aSSimon L. B. Nielsen         break;
370db522d3aSSimon L. B. Nielsen 
371db522d3aSSimon L. B. Nielsen     case CAPI_CMD_LOOKUP_METHOD:
3726f9291ceSJung-uk Kim         if (i < 1 || i > 3) {
373db522d3aSSimon L. B. Nielsen             CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_INVALID_LOOKUP_METHOD);
374e71b7053SJung-uk Kim             BIO_free(out);
375db522d3aSSimon L. B. Nielsen             return 0;
376db522d3aSSimon L. B. Nielsen         }
377db522d3aSSimon L. B. Nielsen         ctx->lookup_method = i;
378db522d3aSSimon L. B. Nielsen         break;
379db522d3aSSimon L. B. Nielsen 
380db522d3aSSimon L. B. Nielsen     case CAPI_CMD_SET_CSP_NAME:
381db522d3aSSimon L. B. Nielsen         ret = capi_ctx_set_provname(ctx, p, ctx->csptype, 1);
382db522d3aSSimon L. B. Nielsen         break;
383db522d3aSSimon L. B. Nielsen 
384db522d3aSSimon L. B. Nielsen     case CAPI_CMD_SET_CSP_TYPE:
385db522d3aSSimon L. B. Nielsen         ctx->csptype = i;
386db522d3aSSimon L. B. Nielsen         break;
387db522d3aSSimon L. B. Nielsen 
388db522d3aSSimon L. B. Nielsen     default:
389db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_CTRL, CAPI_R_UNKNOWN_COMMAND);
390db522d3aSSimon L. B. Nielsen         ret = 0;
391db522d3aSSimon L. B. Nielsen     }
392db522d3aSSimon L. B. Nielsen 
393db522d3aSSimon L. B. Nielsen     BIO_free(out);
394db522d3aSSimon L. B. Nielsen     return ret;
395db522d3aSSimon L. B. Nielsen 
396db522d3aSSimon L. B. Nielsen }
397db522d3aSSimon L. B. Nielsen 
398e71b7053SJung-uk Kim static RSA_METHOD *capi_rsa_method = NULL;
399e71b7053SJung-uk Kim # ifndef OPENSSL_NO_DSA
400e71b7053SJung-uk Kim static DSA_METHOD *capi_dsa_method = NULL;
401e71b7053SJung-uk Kim # endif
402db522d3aSSimon L. B. Nielsen 
403e71b7053SJung-uk Kim static int use_aes_csp = 0;
404e71b7053SJung-uk Kim static const WCHAR rsa_aes_cspname[] =
405e71b7053SJung-uk Kim     L"Microsoft Enhanced RSA and AES Cryptographic Provider";
406e71b7053SJung-uk Kim static const WCHAR rsa_enh_cspname[] =
407e71b7053SJung-uk Kim     L"Microsoft Enhanced Cryptographic Provider v1.0";
408db522d3aSSimon L. B. Nielsen 
capi_init(ENGINE * e)409db522d3aSSimon L. B. Nielsen static int capi_init(ENGINE *e)
410db522d3aSSimon L. B. Nielsen {
411db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
412db522d3aSSimon L. B. Nielsen     const RSA_METHOD *ossl_rsa_meth;
413e71b7053SJung-uk Kim # ifndef OPENSSL_NO_DSA
414db522d3aSSimon L. B. Nielsen     const DSA_METHOD *ossl_dsa_meth;
415e71b7053SJung-uk Kim # endif
416e71b7053SJung-uk Kim     HCRYPTPROV hprov;
417db522d3aSSimon L. B. Nielsen 
4186f9291ceSJung-uk Kim     if (capi_idx < 0) {
41912de4ed2SJung-uk Kim         capi_idx = ENGINE_get_ex_new_index(0, NULL, NULL, NULL, 0);
42012de4ed2SJung-uk Kim         if (capi_idx < 0)
421db522d3aSSimon L. B. Nielsen             goto memerr;
422db522d3aSSimon L. B. Nielsen 
42312de4ed2SJung-uk Kim         cert_capi_idx = X509_get_ex_new_index(0, NULL, NULL, NULL, 0);
42412de4ed2SJung-uk Kim 
425db522d3aSSimon L. B. Nielsen         /* Setup RSA_METHOD */
426db522d3aSSimon L. B. Nielsen         rsa_capi_idx = RSA_get_ex_new_index(0, NULL, NULL, NULL, 0);
427e71b7053SJung-uk Kim         ossl_rsa_meth = RSA_PKCS1_OpenSSL();
428e71b7053SJung-uk Kim         if (   !RSA_meth_set_pub_enc(capi_rsa_method,
429e71b7053SJung-uk Kim                                      RSA_meth_get_pub_enc(ossl_rsa_meth))
430e71b7053SJung-uk Kim             || !RSA_meth_set_pub_dec(capi_rsa_method,
431e71b7053SJung-uk Kim                                      RSA_meth_get_pub_dec(ossl_rsa_meth))
432e71b7053SJung-uk Kim             || !RSA_meth_set_priv_enc(capi_rsa_method, capi_rsa_priv_enc)
433e71b7053SJung-uk Kim             || !RSA_meth_set_priv_dec(capi_rsa_method, capi_rsa_priv_dec)
434e71b7053SJung-uk Kim             || !RSA_meth_set_mod_exp(capi_rsa_method,
435e71b7053SJung-uk Kim                                      RSA_meth_get_mod_exp(ossl_rsa_meth))
436e71b7053SJung-uk Kim             || !RSA_meth_set_bn_mod_exp(capi_rsa_method,
437e71b7053SJung-uk Kim                                         RSA_meth_get_bn_mod_exp(ossl_rsa_meth))
438e71b7053SJung-uk Kim             || !RSA_meth_set_finish(capi_rsa_method, capi_rsa_free)
439e71b7053SJung-uk Kim             || !RSA_meth_set_sign(capi_rsa_method, capi_rsa_sign)) {
440e71b7053SJung-uk Kim             goto memerr;
441e71b7053SJung-uk Kim         }
442db522d3aSSimon L. B. Nielsen 
443e71b7053SJung-uk Kim # ifndef OPENSSL_NO_DSA
444db522d3aSSimon L. B. Nielsen         /* Setup DSA Method */
445db522d3aSSimon L. B. Nielsen         dsa_capi_idx = DSA_get_ex_new_index(0, NULL, NULL, NULL, 0);
446db522d3aSSimon L. B. Nielsen         ossl_dsa_meth = DSA_OpenSSL();
447e71b7053SJung-uk Kim         if (   !DSA_meth_set_sign(capi_dsa_method, capi_dsa_do_sign)
448e71b7053SJung-uk Kim             || !DSA_meth_set_verify(capi_dsa_method,
449e71b7053SJung-uk Kim                                     DSA_meth_get_verify(ossl_dsa_meth))
450e71b7053SJung-uk Kim             || !DSA_meth_set_finish(capi_dsa_method, capi_dsa_free)
451e71b7053SJung-uk Kim             || !DSA_meth_set_mod_exp(capi_dsa_method,
452e71b7053SJung-uk Kim                                      DSA_meth_get_mod_exp(ossl_dsa_meth))
453e71b7053SJung-uk Kim             || !DSA_meth_set_bn_mod_exp(capi_dsa_method,
454e71b7053SJung-uk Kim                                     DSA_meth_get_bn_mod_exp(ossl_dsa_meth))) {
455e71b7053SJung-uk Kim             goto memerr;
456e71b7053SJung-uk Kim         }
457e71b7053SJung-uk Kim # endif
45812de4ed2SJung-uk Kim     }
45912de4ed2SJung-uk Kim 
46012de4ed2SJung-uk Kim     ctx = capi_ctx_new();
461e71b7053SJung-uk Kim     if (ctx == NULL)
46212de4ed2SJung-uk Kim         goto memerr;
46312de4ed2SJung-uk Kim 
46412de4ed2SJung-uk Kim     ENGINE_set_ex_data(e, capi_idx, ctx);
465db522d3aSSimon L. B. Nielsen 
466db522d3aSSimon L. B. Nielsen # ifdef OPENSSL_CAPIENG_DIALOG
467db522d3aSSimon L. B. Nielsen     {
468db522d3aSSimon L. B. Nielsen         HMODULE cryptui = LoadLibrary(TEXT("CRYPTUI.DLL"));
4696a599222SSimon L. B. Nielsen         HMODULE kernel = GetModuleHandle(TEXT("KERNEL32.DLL"));
470db522d3aSSimon L. B. Nielsen         if (cryptui)
4716f9291ceSJung-uk Kim             ctx->certselectdlg =
4726f9291ceSJung-uk Kim                 (CERTDLG) GetProcAddress(cryptui,
4736f9291ceSJung-uk Kim                                          "CryptUIDlgSelectCertificateFromStore");
474db522d3aSSimon L. B. Nielsen         if (kernel)
4756f9291ceSJung-uk Kim             ctx->getconswindow =
4766f9291ceSJung-uk Kim                 (GETCONSWIN) GetProcAddress(kernel, "GetConsoleWindow");
477db522d3aSSimon L. B. Nielsen         if (cryptui && !OPENSSL_isservice())
478db522d3aSSimon L. B. Nielsen             ctx->client_cert_select = cert_select_dialog;
479db522d3aSSimon L. B. Nielsen     }
480db522d3aSSimon L. B. Nielsen # endif
481db522d3aSSimon L. B. Nielsen 
482e71b7053SJung-uk Kim     /* See if there is RSA+AES CSP */
483e71b7053SJung-uk Kim     if (CryptAcquireContextW(&hprov, NULL, rsa_aes_cspname, PROV_RSA_AES,
484e71b7053SJung-uk Kim                              CRYPT_VERIFYCONTEXT)) {
485e71b7053SJung-uk Kim         use_aes_csp = 1;
486e71b7053SJung-uk Kim         CryptReleaseContext(hprov, 0);
487e71b7053SJung-uk Kim     }
488e71b7053SJung-uk Kim 
489db522d3aSSimon L. B. Nielsen     return 1;
490db522d3aSSimon L. B. Nielsen 
491db522d3aSSimon L. B. Nielsen  memerr:
492db522d3aSSimon L. B. Nielsen     CAPIerr(CAPI_F_CAPI_INIT, ERR_R_MALLOC_FAILURE);
493db522d3aSSimon L. B. Nielsen     return 0;
494db522d3aSSimon L. B. Nielsen 
495db522d3aSSimon L. B. Nielsen     return 1;
496db522d3aSSimon L. B. Nielsen }
497db522d3aSSimon L. B. Nielsen 
capi_destroy(ENGINE * e)498db522d3aSSimon L. B. Nielsen static int capi_destroy(ENGINE *e)
499db522d3aSSimon L. B. Nielsen {
500e71b7053SJung-uk Kim     RSA_meth_free(capi_rsa_method);
501e71b7053SJung-uk Kim     capi_rsa_method = NULL;
502e71b7053SJung-uk Kim # ifndef OPENSSL_NO_DSA
503e71b7053SJung-uk Kim     DSA_meth_free(capi_dsa_method);
504e71b7053SJung-uk Kim     capi_dsa_method = NULL;
505e71b7053SJung-uk Kim # endif
506db522d3aSSimon L. B. Nielsen     ERR_unload_CAPI_strings();
507db522d3aSSimon L. B. Nielsen     return 1;
508db522d3aSSimon L. B. Nielsen }
509db522d3aSSimon L. B. Nielsen 
capi_finish(ENGINE * e)510db522d3aSSimon L. B. Nielsen static int capi_finish(ENGINE *e)
511db522d3aSSimon L. B. Nielsen {
512db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
513db522d3aSSimon L. B. Nielsen     ctx = ENGINE_get_ex_data(e, capi_idx);
514db522d3aSSimon L. B. Nielsen     capi_ctx_free(ctx);
515db522d3aSSimon L. B. Nielsen     ENGINE_set_ex_data(e, capi_idx, NULL);
516db522d3aSSimon L. B. Nielsen     return 1;
517db522d3aSSimon L. B. Nielsen }
518db522d3aSSimon L. B. Nielsen 
5196f9291ceSJung-uk Kim /*
5206f9291ceSJung-uk Kim  * CryptoAPI key application data. This contains a handle to the private key
5216f9291ceSJung-uk Kim  * container (for sign operations) and a handle to the key (for decrypt
5226f9291ceSJung-uk Kim  * operations).
523db522d3aSSimon L. B. Nielsen  */
524db522d3aSSimon L. B. Nielsen 
5256f9291ceSJung-uk Kim struct CAPI_KEY_st {
526db522d3aSSimon L. B. Nielsen     /* Associated certificate context (if any) */
527db522d3aSSimon L. B. Nielsen     PCCERT_CONTEXT pcert;
528db522d3aSSimon L. B. Nielsen     HCRYPTPROV hprov;
529db522d3aSSimon L. B. Nielsen     HCRYPTKEY key;
530db522d3aSSimon L. B. Nielsen     DWORD keyspec;
531db522d3aSSimon L. B. Nielsen };
532db522d3aSSimon L. B. Nielsen 
bind_capi(ENGINE * e)533db522d3aSSimon L. B. Nielsen static int bind_capi(ENGINE *e)
534db522d3aSSimon L. B. Nielsen {
535e71b7053SJung-uk Kim     capi_rsa_method = RSA_meth_new("CryptoAPI RSA method", 0);
536e71b7053SJung-uk Kim     if (capi_rsa_method == NULL)
537e71b7053SJung-uk Kim         return 0;
538e71b7053SJung-uk Kim # ifndef OPENSSL_NO_DSA
539e71b7053SJung-uk Kim     capi_dsa_method = DSA_meth_new("CryptoAPI DSA method", 0);
540e71b7053SJung-uk Kim     if (capi_dsa_method == NULL)
541e71b7053SJung-uk Kim         goto memerr;
542e71b7053SJung-uk Kim # endif
543db522d3aSSimon L. B. Nielsen     if (!ENGINE_set_id(e, engine_capi_id)
544db522d3aSSimon L. B. Nielsen         || !ENGINE_set_name(e, engine_capi_name)
5451f13597dSJung-uk Kim         || !ENGINE_set_flags(e, ENGINE_FLAGS_NO_REGISTER_ALL)
546db522d3aSSimon L. B. Nielsen         || !ENGINE_set_init_function(e, capi_init)
547db522d3aSSimon L. B. Nielsen         || !ENGINE_set_finish_function(e, capi_finish)
548db522d3aSSimon L. B. Nielsen         || !ENGINE_set_destroy_function(e, capi_destroy)
549e71b7053SJung-uk Kim         || !ENGINE_set_RSA(e, capi_rsa_method)
550e71b7053SJung-uk Kim # ifndef OPENSSL_NO_DSA
551e71b7053SJung-uk Kim         || !ENGINE_set_DSA(e, capi_dsa_method)
552e71b7053SJung-uk Kim # endif
553db522d3aSSimon L. B. Nielsen         || !ENGINE_set_load_privkey_function(e, capi_load_privkey)
554db522d3aSSimon L. B. Nielsen         || !ENGINE_set_load_ssl_client_cert_function(e,
555db522d3aSSimon L. B. Nielsen                                                      capi_load_ssl_client_cert)
556db522d3aSSimon L. B. Nielsen         || !ENGINE_set_cmd_defns(e, capi_cmd_defns)
557db522d3aSSimon L. B. Nielsen         || !ENGINE_set_ctrl_function(e, capi_ctrl))
558e71b7053SJung-uk Kim         goto memerr;
559db522d3aSSimon L. B. Nielsen     ERR_load_CAPI_strings();
560db522d3aSSimon L. B. Nielsen 
561db522d3aSSimon L. B. Nielsen     return 1;
562e71b7053SJung-uk Kim  memerr:
563e71b7053SJung-uk Kim     RSA_meth_free(capi_rsa_method);
564e71b7053SJung-uk Kim     capi_rsa_method = NULL;
565e71b7053SJung-uk Kim # ifndef OPENSSL_NO_DSA
566e71b7053SJung-uk Kim     DSA_meth_free(capi_dsa_method);
567e71b7053SJung-uk Kim     capi_dsa_method = NULL;
568e71b7053SJung-uk Kim # endif
569e71b7053SJung-uk Kim     return 0;
570db522d3aSSimon L. B. Nielsen }
571db522d3aSSimon L. B. Nielsen 
572db522d3aSSimon L. B. Nielsen # ifndef OPENSSL_NO_DYNAMIC_ENGINE
bind_helper(ENGINE * e,const char * id)573db522d3aSSimon L. B. Nielsen static int bind_helper(ENGINE *e, const char *id)
574db522d3aSSimon L. B. Nielsen {
575db522d3aSSimon L. B. Nielsen     if (id && (strcmp(id, engine_capi_id) != 0))
576db522d3aSSimon L. B. Nielsen         return 0;
577db522d3aSSimon L. B. Nielsen     if (!bind_capi(e))
578db522d3aSSimon L. B. Nielsen         return 0;
579db522d3aSSimon L. B. Nielsen     return 1;
580db522d3aSSimon L. B. Nielsen }
5816f9291ceSJung-uk Kim 
582db522d3aSSimon L. B. Nielsen IMPLEMENT_DYNAMIC_CHECK_FN()
IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)583db522d3aSSimon L. B. Nielsen IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
584db522d3aSSimon L. B. Nielsen # else
585db522d3aSSimon L. B. Nielsen static ENGINE *engine_capi(void)
586db522d3aSSimon L. B. Nielsen {
587db522d3aSSimon L. B. Nielsen     ENGINE *ret = ENGINE_new();
588e71b7053SJung-uk Kim     if (ret == NULL)
589db522d3aSSimon L. B. Nielsen         return NULL;
5906f9291ceSJung-uk Kim     if (!bind_capi(ret)) {
591db522d3aSSimon L. B. Nielsen         ENGINE_free(ret);
592db522d3aSSimon L. B. Nielsen         return NULL;
593db522d3aSSimon L. B. Nielsen     }
594db522d3aSSimon L. B. Nielsen     return ret;
595db522d3aSSimon L. B. Nielsen }
596db522d3aSSimon L. B. Nielsen 
597e71b7053SJung-uk Kim void engine_load_capi_int(void)
598db522d3aSSimon L. B. Nielsen {
599db522d3aSSimon L. B. Nielsen     /* Copied from eng_[openssl|dyn].c */
600db522d3aSSimon L. B. Nielsen     ENGINE *toadd = engine_capi();
6016f9291ceSJung-uk Kim     if (!toadd)
6026f9291ceSJung-uk Kim         return;
603*b077aed3SPierre Pronchery     ERR_set_mark();
604db522d3aSSimon L. B. Nielsen     ENGINE_add(toadd);
605*b077aed3SPierre Pronchery     /*
606*b077aed3SPierre Pronchery      * If the "add" worked, it gets a structural reference. So either way, we
607*b077aed3SPierre Pronchery      * release our just-created reference.
608*b077aed3SPierre Pronchery      */
609db522d3aSSimon L. B. Nielsen     ENGINE_free(toadd);
610*b077aed3SPierre Pronchery     /*
611*b077aed3SPierre Pronchery      * If the "add" didn't work, it was probably a conflict because it was
612*b077aed3SPierre Pronchery      * already added (eg. someone calling ENGINE_load_blah then calling
613*b077aed3SPierre Pronchery      * ENGINE_load_builtin_engines() perhaps).
614*b077aed3SPierre Pronchery      */
615*b077aed3SPierre Pronchery     ERR_pop_to_mark();
616db522d3aSSimon L. B. Nielsen }
617db522d3aSSimon L. B. Nielsen # endif
618db522d3aSSimon L. B. Nielsen 
619db522d3aSSimon L. B. Nielsen static int lend_tobn(BIGNUM *bn, unsigned char *bin, int binlen)
620db522d3aSSimon L. B. Nielsen {
621db522d3aSSimon L. B. Nielsen     int i;
6226f9291ceSJung-uk Kim     /*
6236f9291ceSJung-uk Kim      * Reverse buffer in place: since this is a keyblob structure that will
6246f9291ceSJung-uk Kim      * be freed up after conversion anyway it doesn't matter if we change
6256f9291ceSJung-uk Kim      * it.
626db522d3aSSimon L. B. Nielsen      */
6276f9291ceSJung-uk Kim     for (i = 0; i < binlen / 2; i++) {
628db522d3aSSimon L. B. Nielsen         unsigned char c;
629db522d3aSSimon L. B. Nielsen         c = bin[i];
630db522d3aSSimon L. B. Nielsen         bin[i] = bin[binlen - i - 1];
631db522d3aSSimon L. B. Nielsen         bin[binlen - i - 1] = c;
632db522d3aSSimon L. B. Nielsen     }
633db522d3aSSimon L. B. Nielsen 
634db522d3aSSimon L. B. Nielsen     if (!BN_bin2bn(bin, binlen, bn))
635db522d3aSSimon L. B. Nielsen         return 0;
636db522d3aSSimon L. B. Nielsen     return 1;
637db522d3aSSimon L. B. Nielsen }
638db522d3aSSimon L. B. Nielsen 
639db522d3aSSimon L. B. Nielsen /* Given a CAPI_KEY get an EVP_PKEY structure */
640db522d3aSSimon L. B. Nielsen 
capi_get_pkey(ENGINE * eng,CAPI_KEY * key)641db522d3aSSimon L. B. Nielsen static EVP_PKEY *capi_get_pkey(ENGINE *eng, CAPI_KEY *key)
642db522d3aSSimon L. B. Nielsen {
643db522d3aSSimon L. B. Nielsen     unsigned char *pubkey = NULL;
644db522d3aSSimon L. B. Nielsen     DWORD len;
645db522d3aSSimon L. B. Nielsen     BLOBHEADER *bh;
646db522d3aSSimon L. B. Nielsen     RSA *rkey = NULL;
647db522d3aSSimon L. B. Nielsen     DSA *dkey = NULL;
648db522d3aSSimon L. B. Nielsen     EVP_PKEY *ret = NULL;
6496f9291ceSJung-uk Kim     if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, NULL, &len)) {
650db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_LENGTH_ERROR);
651db522d3aSSimon L. B. Nielsen         capi_addlasterror();
652db522d3aSSimon L. B. Nielsen         return NULL;
653db522d3aSSimon L. B. Nielsen     }
654db522d3aSSimon L. B. Nielsen 
655db522d3aSSimon L. B. Nielsen     pubkey = OPENSSL_malloc(len);
656db522d3aSSimon L. B. Nielsen 
657e71b7053SJung-uk Kim     if (pubkey == NULL)
658db522d3aSSimon L. B. Nielsen         goto memerr;
659db522d3aSSimon L. B. Nielsen 
6606f9291ceSJung-uk Kim     if (!CryptExportKey(key->key, 0, PUBLICKEYBLOB, 0, pubkey, &len)) {
661db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_PUBKEY_EXPORT_ERROR);
662db522d3aSSimon L. B. Nielsen         capi_addlasterror();
663db522d3aSSimon L. B. Nielsen         goto err;
664db522d3aSSimon L. B. Nielsen     }
665db522d3aSSimon L. B. Nielsen 
666db522d3aSSimon L. B. Nielsen     bh = (BLOBHEADER *) pubkey;
6676f9291ceSJung-uk Kim     if (bh->bType != PUBLICKEYBLOB) {
668db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_PKEY, CAPI_R_INVALID_PUBLIC_KEY_BLOB);
669db522d3aSSimon L. B. Nielsen         goto err;
670db522d3aSSimon L. B. Nielsen     }
6716f9291ceSJung-uk Kim     if (bh->aiKeyAlg == CALG_RSA_SIGN || bh->aiKeyAlg == CALG_RSA_KEYX) {
672db522d3aSSimon L. B. Nielsen         RSAPUBKEY *rp;
673db522d3aSSimon L. B. Nielsen         DWORD rsa_modlen;
674e71b7053SJung-uk Kim         BIGNUM *e = NULL, *n = NULL;
675db522d3aSSimon L. B. Nielsen         unsigned char *rsa_modulus;
676db522d3aSSimon L. B. Nielsen         rp = (RSAPUBKEY *) (bh + 1);
6776f9291ceSJung-uk Kim         if (rp->magic != 0x31415352) {
678db522d3aSSimon L. B. Nielsen             char magstr[10];
679db522d3aSSimon L. B. Nielsen             BIO_snprintf(magstr, 10, "%lx", rp->magic);
6806f9291ceSJung-uk Kim             CAPIerr(CAPI_F_CAPI_GET_PKEY,
6816f9291ceSJung-uk Kim                     CAPI_R_INVALID_RSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER);
682db522d3aSSimon L. B. Nielsen             ERR_add_error_data(2, "magic=0x", magstr);
683db522d3aSSimon L. B. Nielsen             goto err;
684db522d3aSSimon L. B. Nielsen         }
685db522d3aSSimon L. B. Nielsen         rsa_modulus = (unsigned char *)(rp + 1);
686db522d3aSSimon L. B. Nielsen         rkey = RSA_new_method(eng);
687db522d3aSSimon L. B. Nielsen         if (!rkey)
688db522d3aSSimon L. B. Nielsen             goto memerr;
689db522d3aSSimon L. B. Nielsen 
690e71b7053SJung-uk Kim         e = BN_new();
691e71b7053SJung-uk Kim         n = BN_new();
692db522d3aSSimon L. B. Nielsen 
693e71b7053SJung-uk Kim         if (e == NULL || n == NULL) {
694e71b7053SJung-uk Kim             BN_free(e);
695e71b7053SJung-uk Kim             BN_free(n);
696db522d3aSSimon L. B. Nielsen             goto memerr;
697e71b7053SJung-uk Kim         }
698db522d3aSSimon L. B. Nielsen 
699e71b7053SJung-uk Kim         RSA_set0_key(rkey, n, e, NULL);
700e71b7053SJung-uk Kim 
701e71b7053SJung-uk Kim         if (!BN_set_word(e, rp->pubexp))
702db522d3aSSimon L. B. Nielsen             goto memerr;
703db522d3aSSimon L. B. Nielsen 
704db522d3aSSimon L. B. Nielsen         rsa_modlen = rp->bitlen / 8;
705e71b7053SJung-uk Kim         if (!lend_tobn(n, rsa_modulus, rsa_modlen))
706db522d3aSSimon L. B. Nielsen             goto memerr;
707db522d3aSSimon L. B. Nielsen 
708db522d3aSSimon L. B. Nielsen         RSA_set_ex_data(rkey, rsa_capi_idx, key);
709db522d3aSSimon L. B. Nielsen 
710e71b7053SJung-uk Kim         if ((ret = EVP_PKEY_new()) == NULL)
711db522d3aSSimon L. B. Nielsen             goto memerr;
712db522d3aSSimon L. B. Nielsen 
713db522d3aSSimon L. B. Nielsen         EVP_PKEY_assign_RSA(ret, rkey);
714db522d3aSSimon L. B. Nielsen         rkey = NULL;
715db522d3aSSimon L. B. Nielsen 
716e71b7053SJung-uk Kim # ifndef OPENSSL_NO_DSA
7176f9291ceSJung-uk Kim     } else if (bh->aiKeyAlg == CALG_DSS_SIGN) {
718db522d3aSSimon L. B. Nielsen         DSSPUBKEY *dp;
719db522d3aSSimon L. B. Nielsen         DWORD dsa_plen;
720db522d3aSSimon L. B. Nielsen         unsigned char *btmp;
721e71b7053SJung-uk Kim         BIGNUM *p, *q, *g, *pub_key;
722db522d3aSSimon L. B. Nielsen         dp = (DSSPUBKEY *) (bh + 1);
7236f9291ceSJung-uk Kim         if (dp->magic != 0x31535344) {
724db522d3aSSimon L. B. Nielsen             char magstr[10];
725db522d3aSSimon L. B. Nielsen             BIO_snprintf(magstr, 10, "%lx", dp->magic);
7266f9291ceSJung-uk Kim             CAPIerr(CAPI_F_CAPI_GET_PKEY,
7276f9291ceSJung-uk Kim                     CAPI_R_INVALID_DSA_PUBLIC_KEY_BLOB_MAGIC_NUMBER);
728db522d3aSSimon L. B. Nielsen             ERR_add_error_data(2, "magic=0x", magstr);
729db522d3aSSimon L. B. Nielsen             goto err;
730db522d3aSSimon L. B. Nielsen         }
731db522d3aSSimon L. B. Nielsen         dsa_plen = dp->bitlen / 8;
732db522d3aSSimon L. B. Nielsen         btmp = (unsigned char *)(dp + 1);
733db522d3aSSimon L. B. Nielsen         dkey = DSA_new_method(eng);
734db522d3aSSimon L. B. Nielsen         if (!dkey)
735db522d3aSSimon L. B. Nielsen             goto memerr;
736e71b7053SJung-uk Kim         p = BN_new();
737e71b7053SJung-uk Kim         q = BN_new();
738e71b7053SJung-uk Kim         g = BN_new();
739e71b7053SJung-uk Kim         pub_key = BN_new();
740e71b7053SJung-uk Kim         if (p == NULL || q == NULL || g == NULL || pub_key == NULL) {
741e71b7053SJung-uk Kim             BN_free(p);
742e71b7053SJung-uk Kim             BN_free(q);
743e71b7053SJung-uk Kim             BN_free(g);
744e71b7053SJung-uk Kim             BN_free(pub_key);
745db522d3aSSimon L. B. Nielsen             goto memerr;
746e71b7053SJung-uk Kim         }
747e71b7053SJung-uk Kim         DSA_set0_pqg(dkey, p, q, g);
748e71b7053SJung-uk Kim         DSA_set0_key(dkey, pub_key, NULL);
749e71b7053SJung-uk Kim         if (!lend_tobn(p, btmp, dsa_plen))
750db522d3aSSimon L. B. Nielsen             goto memerr;
751db522d3aSSimon L. B. Nielsen         btmp += dsa_plen;
752e71b7053SJung-uk Kim         if (!lend_tobn(q, btmp, 20))
753db522d3aSSimon L. B. Nielsen             goto memerr;
754db522d3aSSimon L. B. Nielsen         btmp += 20;
755e71b7053SJung-uk Kim         if (!lend_tobn(g, btmp, dsa_plen))
756db522d3aSSimon L. B. Nielsen             goto memerr;
757db522d3aSSimon L. B. Nielsen         btmp += dsa_plen;
758e71b7053SJung-uk Kim         if (!lend_tobn(pub_key, btmp, dsa_plen))
759db522d3aSSimon L. B. Nielsen             goto memerr;
760db522d3aSSimon L. B. Nielsen         btmp += dsa_plen;
761db522d3aSSimon L. B. Nielsen 
762db522d3aSSimon L. B. Nielsen         DSA_set_ex_data(dkey, dsa_capi_idx, key);
763db522d3aSSimon L. B. Nielsen 
764e71b7053SJung-uk Kim         if ((ret = EVP_PKEY_new()) == NULL)
765db522d3aSSimon L. B. Nielsen             goto memerr;
766db522d3aSSimon L. B. Nielsen 
767db522d3aSSimon L. B. Nielsen         EVP_PKEY_assign_DSA(ret, dkey);
768db522d3aSSimon L. B. Nielsen         dkey = NULL;
769e71b7053SJung-uk Kim # endif
7706f9291ceSJung-uk Kim     } else {
771db522d3aSSimon L. B. Nielsen         char algstr[10];
772e71b7053SJung-uk Kim         BIO_snprintf(algstr, 10, "%ux", bh->aiKeyAlg);
7736f9291ceSJung-uk Kim         CAPIerr(CAPI_F_CAPI_GET_PKEY,
7746f9291ceSJung-uk Kim                 CAPI_R_UNSUPPORTED_PUBLIC_KEY_ALGORITHM);
775db522d3aSSimon L. B. Nielsen         ERR_add_error_data(2, "aiKeyAlg=0x", algstr);
776db522d3aSSimon L. B. Nielsen         goto err;
777db522d3aSSimon L. B. Nielsen     }
778db522d3aSSimon L. B. Nielsen 
779db522d3aSSimon L. B. Nielsen  err:
780db522d3aSSimon L. B. Nielsen     OPENSSL_free(pubkey);
7816f9291ceSJung-uk Kim     if (!ret) {
782db522d3aSSimon L. B. Nielsen         RSA_free(rkey);
783e71b7053SJung-uk Kim # ifndef OPENSSL_NO_DSA
784db522d3aSSimon L. B. Nielsen         DSA_free(dkey);
785e71b7053SJung-uk Kim # endif
786db522d3aSSimon L. B. Nielsen     }
787db522d3aSSimon L. B. Nielsen 
788db522d3aSSimon L. B. Nielsen     return ret;
789db522d3aSSimon L. B. Nielsen 
790db522d3aSSimon L. B. Nielsen  memerr:
791db522d3aSSimon L. B. Nielsen     CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_MALLOC_FAILURE);
792db522d3aSSimon L. B. Nielsen     goto err;
793db522d3aSSimon L. B. Nielsen 
794db522d3aSSimon L. B. Nielsen }
795db522d3aSSimon L. B. Nielsen 
capi_load_privkey(ENGINE * eng,const char * key_id,UI_METHOD * ui_method,void * callback_data)796db522d3aSSimon L. B. Nielsen static EVP_PKEY *capi_load_privkey(ENGINE *eng, const char *key_id,
797db522d3aSSimon L. B. Nielsen                                    UI_METHOD *ui_method, void *callback_data)
798db522d3aSSimon L. B. Nielsen {
799db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
800db522d3aSSimon L. B. Nielsen     CAPI_KEY *key;
801db522d3aSSimon L. B. Nielsen     EVP_PKEY *ret;
802db522d3aSSimon L. B. Nielsen     ctx = ENGINE_get_ex_data(eng, capi_idx);
803db522d3aSSimon L. B. Nielsen 
8046f9291ceSJung-uk Kim     if (!ctx) {
805db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_LOAD_PRIVKEY, CAPI_R_CANT_FIND_CAPI_CONTEXT);
806db522d3aSSimon L. B. Nielsen         return NULL;
807db522d3aSSimon L. B. Nielsen     }
808db522d3aSSimon L. B. Nielsen 
809db522d3aSSimon L. B. Nielsen     key = capi_find_key(ctx, key_id);
810db522d3aSSimon L. B. Nielsen 
811db522d3aSSimon L. B. Nielsen     if (!key)
812db522d3aSSimon L. B. Nielsen         return NULL;
813db522d3aSSimon L. B. Nielsen 
814db522d3aSSimon L. B. Nielsen     ret = capi_get_pkey(eng, key);
815db522d3aSSimon L. B. Nielsen 
816db522d3aSSimon L. B. Nielsen     if (!ret)
817db522d3aSSimon L. B. Nielsen         capi_free_key(key);
818db522d3aSSimon L. B. Nielsen     return ret;
819db522d3aSSimon L. B. Nielsen 
820db522d3aSSimon L. B. Nielsen }
821db522d3aSSimon L. B. Nielsen 
822db522d3aSSimon L. B. Nielsen /* CryptoAPI RSA operations */
823db522d3aSSimon L. B. Nielsen 
capi_rsa_priv_enc(int flen,const unsigned char * from,unsigned char * to,RSA * rsa,int padding)824db522d3aSSimon L. B. Nielsen int capi_rsa_priv_enc(int flen, const unsigned char *from,
825db522d3aSSimon L. B. Nielsen                       unsigned char *to, RSA *rsa, int padding)
826db522d3aSSimon L. B. Nielsen {
827db522d3aSSimon L. B. Nielsen     CAPIerr(CAPI_F_CAPI_RSA_PRIV_ENC, CAPI_R_FUNCTION_NOT_SUPPORTED);
828db522d3aSSimon L. B. Nielsen     return -1;
829db522d3aSSimon L. B. Nielsen }
830db522d3aSSimon L. B. Nielsen 
capi_rsa_sign(int dtype,const unsigned char * m,unsigned int m_len,unsigned char * sigret,unsigned int * siglen,const RSA * rsa)831db522d3aSSimon L. B. Nielsen int capi_rsa_sign(int dtype, const unsigned char *m, unsigned int m_len,
832db522d3aSSimon L. B. Nielsen                   unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
833db522d3aSSimon L. B. Nielsen {
834db522d3aSSimon L. B. Nielsen     ALG_ID alg;
835db522d3aSSimon L. B. Nielsen     HCRYPTHASH hash;
836db522d3aSSimon L. B. Nielsen     DWORD slen;
837db522d3aSSimon L. B. Nielsen     unsigned int i;
838db522d3aSSimon L. B. Nielsen     int ret = -1;
839db522d3aSSimon L. B. Nielsen     CAPI_KEY *capi_key;
840db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
841db522d3aSSimon L. B. Nielsen 
842e71b7053SJung-uk Kim     ctx = ENGINE_get_ex_data(RSA_get0_engine(rsa), capi_idx);
843db522d3aSSimon L. B. Nielsen 
844db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "Called CAPI_rsa_sign()\n");
845db522d3aSSimon L. B. Nielsen 
846db522d3aSSimon L. B. Nielsen     capi_key = RSA_get_ex_data(rsa, rsa_capi_idx);
8476f9291ceSJung-uk Kim     if (!capi_key) {
848db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_GET_KEY);
849db522d3aSSimon L. B. Nielsen         return -1;
850db522d3aSSimon L. B. Nielsen     }
851db522d3aSSimon L. B. Nielsen     /* Convert the signature type to a CryptoAPI algorithm ID */
8526f9291ceSJung-uk Kim     switch (dtype) {
8534c6a0400SJung-uk Kim     case NID_sha256:
8544c6a0400SJung-uk Kim         alg = CALG_SHA_256;
8554c6a0400SJung-uk Kim         break;
8564c6a0400SJung-uk Kim 
8574c6a0400SJung-uk Kim     case NID_sha384:
8584c6a0400SJung-uk Kim         alg = CALG_SHA_384;
8594c6a0400SJung-uk Kim         break;
8604c6a0400SJung-uk Kim 
8614c6a0400SJung-uk Kim     case NID_sha512:
8624c6a0400SJung-uk Kim         alg = CALG_SHA_512;
8634c6a0400SJung-uk Kim         break;
8644c6a0400SJung-uk Kim 
865db522d3aSSimon L. B. Nielsen     case NID_sha1:
866db522d3aSSimon L. B. Nielsen         alg = CALG_SHA1;
867db522d3aSSimon L. B. Nielsen         break;
868db522d3aSSimon L. B. Nielsen 
869db522d3aSSimon L. B. Nielsen     case NID_md5:
870db522d3aSSimon L. B. Nielsen         alg = CALG_MD5;
871db522d3aSSimon L. B. Nielsen         break;
872db522d3aSSimon L. B. Nielsen 
873db522d3aSSimon L. B. Nielsen     case NID_md5_sha1:
874db522d3aSSimon L. B. Nielsen         alg = CALG_SSL3_SHAMD5;
875db522d3aSSimon L. B. Nielsen         break;
876db522d3aSSimon L. B. Nielsen     default:
877db522d3aSSimon L. B. Nielsen         {
878db522d3aSSimon L. B. Nielsen             char algstr[10];
879e71b7053SJung-uk Kim             BIO_snprintf(algstr, 10, "%x", dtype);
880db522d3aSSimon L. B. Nielsen             CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_UNSUPPORTED_ALGORITHM_NID);
881db522d3aSSimon L. B. Nielsen             ERR_add_error_data(2, "NID=0x", algstr);
882db522d3aSSimon L. B. Nielsen             return -1;
883db522d3aSSimon L. B. Nielsen         }
884db522d3aSSimon L. B. Nielsen     }
885db522d3aSSimon L. B. Nielsen 
886db522d3aSSimon L. B. Nielsen     /* Create the hash object */
8876f9291ceSJung-uk Kim     if (!CryptCreateHash(capi_key->hprov, alg, 0, 0, &hash)) {
888db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT);
889db522d3aSSimon L. B. Nielsen         capi_addlasterror();
890db522d3aSSimon L. B. Nielsen         return -1;
891db522d3aSSimon L. B. Nielsen     }
892db522d3aSSimon L. B. Nielsen     /* Set the hash value to the value passed */
893db522d3aSSimon L. B. Nielsen 
8946f9291ceSJung-uk Kim     if (!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)m, 0)) {
895db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_CANT_SET_HASH_VALUE);
896db522d3aSSimon L. B. Nielsen         capi_addlasterror();
897db522d3aSSimon L. B. Nielsen         goto err;
898db522d3aSSimon L. B. Nielsen     }
899db522d3aSSimon L. B. Nielsen 
900db522d3aSSimon L. B. Nielsen     /* Finally sign it */
901db522d3aSSimon L. B. Nielsen     slen = RSA_size(rsa);
9027bded2dbSJung-uk Kim     if (!CryptSignHash(hash, capi_key->keyspec, NULL, 0, sigret, &slen)) {
903db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_ERROR_SIGNING_HASH);
904db522d3aSSimon L. B. Nielsen         capi_addlasterror();
905db522d3aSSimon L. B. Nielsen         goto err;
9066f9291ceSJung-uk Kim     } else {
907db522d3aSSimon L. B. Nielsen         ret = 1;
908db522d3aSSimon L. B. Nielsen         /* Inplace byte reversal of signature */
9096f9291ceSJung-uk Kim         for (i = 0; i < slen / 2; i++) {
910db522d3aSSimon L. B. Nielsen             unsigned char c;
911db522d3aSSimon L. B. Nielsen             c = sigret[i];
912db522d3aSSimon L. B. Nielsen             sigret[i] = sigret[slen - i - 1];
913db522d3aSSimon L. B. Nielsen             sigret[slen - i - 1] = c;
914db522d3aSSimon L. B. Nielsen         }
915db522d3aSSimon L. B. Nielsen         *siglen = slen;
916db522d3aSSimon L. B. Nielsen     }
917db522d3aSSimon L. B. Nielsen 
918db522d3aSSimon L. B. Nielsen     /* Now cleanup */
919db522d3aSSimon L. B. Nielsen 
920db522d3aSSimon L. B. Nielsen  err:
921db522d3aSSimon L. B. Nielsen     CryptDestroyHash(hash);
922db522d3aSSimon L. B. Nielsen 
923db522d3aSSimon L. B. Nielsen     return ret;
924db522d3aSSimon L. B. Nielsen }
925db522d3aSSimon L. B. Nielsen 
capi_rsa_priv_dec(int flen,const unsigned char * from,unsigned char * to,RSA * rsa,int padding)926db522d3aSSimon L. B. Nielsen int capi_rsa_priv_dec(int flen, const unsigned char *from,
927db522d3aSSimon L. B. Nielsen                       unsigned char *to, RSA *rsa, int padding)
928db522d3aSSimon L. B. Nielsen {
929db522d3aSSimon L. B. Nielsen     int i;
930db522d3aSSimon L. B. Nielsen     unsigned char *tmpbuf;
931db522d3aSSimon L. B. Nielsen     CAPI_KEY *capi_key;
932db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
933e71b7053SJung-uk Kim     DWORD flags = 0;
934e71b7053SJung-uk Kim     DWORD dlen;
935e71b7053SJung-uk Kim 
936e71b7053SJung-uk Kim     if (flen <= 0)
937e71b7053SJung-uk Kim         return flen;
938e71b7053SJung-uk Kim 
939e71b7053SJung-uk Kim     ctx = ENGINE_get_ex_data(RSA_get0_engine(rsa), capi_idx);
940db522d3aSSimon L. B. Nielsen 
941db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "Called capi_rsa_priv_dec()\n");
942db522d3aSSimon L. B. Nielsen 
943db522d3aSSimon L. B. Nielsen     capi_key = RSA_get_ex_data(rsa, rsa_capi_idx);
9446f9291ceSJung-uk Kim     if (!capi_key) {
945db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_CANT_GET_KEY);
946db522d3aSSimon L. B. Nielsen         return -1;
947db522d3aSSimon L. B. Nielsen     }
948db522d3aSSimon L. B. Nielsen 
949e71b7053SJung-uk Kim     switch (padding) {
950e71b7053SJung-uk Kim     case RSA_PKCS1_PADDING:
951e71b7053SJung-uk Kim         /* Nothing to do */
952e71b7053SJung-uk Kim         break;
953e71b7053SJung-uk Kim #ifdef CRYPT_DECRYPT_RSA_NO_PADDING_CHECK
954e71b7053SJung-uk Kim     case RSA_NO_PADDING:
955e71b7053SJung-uk Kim         flags = CRYPT_DECRYPT_RSA_NO_PADDING_CHECK;
956e71b7053SJung-uk Kim         break;
957e71b7053SJung-uk Kim #endif
958e71b7053SJung-uk Kim     default:
959e71b7053SJung-uk Kim         {
960db522d3aSSimon L. B. Nielsen             char errstr[10];
961db522d3aSSimon L. B. Nielsen             BIO_snprintf(errstr, 10, "%d", padding);
962db522d3aSSimon L. B. Nielsen             CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_UNSUPPORTED_PADDING);
963db522d3aSSimon L. B. Nielsen             ERR_add_error_data(2, "padding=", errstr);
964db522d3aSSimon L. B. Nielsen             return -1;
965db522d3aSSimon L. B. Nielsen         }
966e71b7053SJung-uk Kim     }
967db522d3aSSimon L. B. Nielsen 
968db522d3aSSimon L. B. Nielsen     /* Create temp reverse order version of input */
969e71b7053SJung-uk Kim     if ((tmpbuf = OPENSSL_malloc(flen)) == NULL) {
970db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, ERR_R_MALLOC_FAILURE);
971db522d3aSSimon L. B. Nielsen         return -1;
972db522d3aSSimon L. B. Nielsen     }
973db522d3aSSimon L. B. Nielsen     for (i = 0; i < flen; i++)
974db522d3aSSimon L. B. Nielsen         tmpbuf[flen - i - 1] = from[i];
975db522d3aSSimon L. B. Nielsen 
976db522d3aSSimon L. B. Nielsen     /* Finally decrypt it */
977e71b7053SJung-uk Kim     dlen = flen;
978e71b7053SJung-uk Kim     if (!CryptDecrypt(capi_key->key, 0, TRUE, flags, tmpbuf, &dlen)) {
979db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_RSA_PRIV_DEC, CAPI_R_DECRYPT_ERROR);
980db522d3aSSimon L. B. Nielsen         capi_addlasterror();
981e71b7053SJung-uk Kim         OPENSSL_cleanse(tmpbuf, dlen);
982db522d3aSSimon L. B. Nielsen         OPENSSL_free(tmpbuf);
983db522d3aSSimon L. B. Nielsen         return -1;
984e71b7053SJung-uk Kim     } else {
985e71b7053SJung-uk Kim         memcpy(to, tmpbuf, (flen = (int)dlen));
986e71b7053SJung-uk Kim     }
987e71b7053SJung-uk Kim     OPENSSL_cleanse(tmpbuf, flen);
988db522d3aSSimon L. B. Nielsen     OPENSSL_free(tmpbuf);
989db522d3aSSimon L. B. Nielsen 
990db522d3aSSimon L. B. Nielsen     return flen;
991db522d3aSSimon L. B. Nielsen }
992db522d3aSSimon L. B. Nielsen 
capi_rsa_free(RSA * rsa)993db522d3aSSimon L. B. Nielsen static int capi_rsa_free(RSA *rsa)
994db522d3aSSimon L. B. Nielsen {
995db522d3aSSimon L. B. Nielsen     CAPI_KEY *capi_key;
996db522d3aSSimon L. B. Nielsen     capi_key = RSA_get_ex_data(rsa, rsa_capi_idx);
997db522d3aSSimon L. B. Nielsen     capi_free_key(capi_key);
998db522d3aSSimon L. B. Nielsen     RSA_set_ex_data(rsa, rsa_capi_idx, 0);
999db522d3aSSimon L. B. Nielsen     return 1;
1000db522d3aSSimon L. B. Nielsen }
1001db522d3aSSimon L. B. Nielsen 
1002e71b7053SJung-uk Kim # ifndef OPENSSL_NO_DSA
1003db522d3aSSimon L. B. Nielsen /* CryptoAPI DSA operations */
1004db522d3aSSimon L. B. Nielsen 
capi_dsa_do_sign(const unsigned char * digest,int dlen,DSA * dsa)1005db522d3aSSimon L. B. Nielsen static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen,
1006db522d3aSSimon L. B. Nielsen                                  DSA *dsa)
1007db522d3aSSimon L. B. Nielsen {
1008db522d3aSSimon L. B. Nielsen     HCRYPTHASH hash;
1009db522d3aSSimon L. B. Nielsen     DWORD slen;
1010db522d3aSSimon L. B. Nielsen     DSA_SIG *ret = NULL;
1011db522d3aSSimon L. B. Nielsen     CAPI_KEY *capi_key;
1012db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
1013db522d3aSSimon L. B. Nielsen     unsigned char csigbuf[40];
1014db522d3aSSimon L. B. Nielsen 
1015e71b7053SJung-uk Kim     ctx = ENGINE_get_ex_data(DSA_get0_engine(dsa), capi_idx);
1016db522d3aSSimon L. B. Nielsen 
1017db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "Called CAPI_dsa_do_sign()\n");
1018db522d3aSSimon L. B. Nielsen 
1019db522d3aSSimon L. B. Nielsen     capi_key = DSA_get_ex_data(dsa, dsa_capi_idx);
1020db522d3aSSimon L. B. Nielsen 
10216f9291ceSJung-uk Kim     if (!capi_key) {
1022db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_GET_KEY);
1023db522d3aSSimon L. B. Nielsen         return NULL;
1024db522d3aSSimon L. B. Nielsen     }
1025db522d3aSSimon L. B. Nielsen 
10266f9291ceSJung-uk Kim     if (dlen != 20) {
1027db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_INVALID_DIGEST_LENGTH);
1028db522d3aSSimon L. B. Nielsen         return NULL;
1029db522d3aSSimon L. B. Nielsen     }
1030db522d3aSSimon L. B. Nielsen 
1031db522d3aSSimon L. B. Nielsen     /* Create the hash object */
10326f9291ceSJung-uk Kim     if (!CryptCreateHash(capi_key->hprov, CALG_SHA1, 0, 0, &hash)) {
1033db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT);
1034db522d3aSSimon L. B. Nielsen         capi_addlasterror();
1035db522d3aSSimon L. B. Nielsen         return NULL;
1036db522d3aSSimon L. B. Nielsen     }
1037db522d3aSSimon L. B. Nielsen 
1038db522d3aSSimon L. B. Nielsen     /* Set the hash value to the value passed */
10396f9291ceSJung-uk Kim     if (!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)digest, 0)) {
1040db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_SET_HASH_VALUE);
1041db522d3aSSimon L. B. Nielsen         capi_addlasterror();
1042db522d3aSSimon L. B. Nielsen         goto err;
1043db522d3aSSimon L. B. Nielsen     }
1044db522d3aSSimon L. B. Nielsen 
1045db522d3aSSimon L. B. Nielsen     /* Finally sign it */
1046db522d3aSSimon L. B. Nielsen     slen = sizeof(csigbuf);
10477bded2dbSJung-uk Kim     if (!CryptSignHash(hash, capi_key->keyspec, NULL, 0, csigbuf, &slen)) {
1048db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_ERROR_SIGNING_HASH);
1049db522d3aSSimon L. B. Nielsen         capi_addlasterror();
1050db522d3aSSimon L. B. Nielsen         goto err;
10516f9291ceSJung-uk Kim     } else {
1052e71b7053SJung-uk Kim         BIGNUM *r = BN_new(), *s = BN_new();
1053e71b7053SJung-uk Kim 
1054e71b7053SJung-uk Kim         if (r == NULL || s == NULL
1055e71b7053SJung-uk Kim             || !lend_tobn(r, csigbuf, 20)
1056e71b7053SJung-uk Kim             || !lend_tobn(s, csigbuf + 20, 20)
1057e71b7053SJung-uk Kim             || (ret = DSA_SIG_new()) == NULL) {
1058e71b7053SJung-uk Kim             BN_free(r); /* BN_free checks for BIGNUM * being NULL */
1059e71b7053SJung-uk Kim             BN_free(s);
1060db522d3aSSimon L. B. Nielsen             goto err;
1061db522d3aSSimon L. B. Nielsen         }
1062e71b7053SJung-uk Kim         DSA_SIG_set0(ret, r, s);
1063db522d3aSSimon L. B. Nielsen     }
1064db522d3aSSimon L. B. Nielsen 
1065db522d3aSSimon L. B. Nielsen     /* Now cleanup */
1066db522d3aSSimon L. B. Nielsen 
1067db522d3aSSimon L. B. Nielsen  err:
1068db522d3aSSimon L. B. Nielsen     OPENSSL_cleanse(csigbuf, 40);
1069db522d3aSSimon L. B. Nielsen     CryptDestroyHash(hash);
1070db522d3aSSimon L. B. Nielsen     return ret;
1071db522d3aSSimon L. B. Nielsen }
1072db522d3aSSimon L. B. Nielsen 
capi_dsa_free(DSA * dsa)1073db522d3aSSimon L. B. Nielsen static int capi_dsa_free(DSA *dsa)
1074db522d3aSSimon L. B. Nielsen {
1075db522d3aSSimon L. B. Nielsen     CAPI_KEY *capi_key;
1076db522d3aSSimon L. B. Nielsen     capi_key = DSA_get_ex_data(dsa, dsa_capi_idx);
1077db522d3aSSimon L. B. Nielsen     capi_free_key(capi_key);
1078db522d3aSSimon L. B. Nielsen     DSA_set_ex_data(dsa, dsa_capi_idx, 0);
1079db522d3aSSimon L. B. Nielsen     return 1;
1080db522d3aSSimon L. B. Nielsen }
1081e71b7053SJung-uk Kim # endif
1082db522d3aSSimon L. B. Nielsen 
capi_vtrace(CAPI_CTX * ctx,int level,char * format,va_list argptr)10836f9291ceSJung-uk Kim static void capi_vtrace(CAPI_CTX *ctx, int level, char *format,
10846f9291ceSJung-uk Kim                         va_list argptr)
1085db522d3aSSimon L. B. Nielsen {
1086db522d3aSSimon L. B. Nielsen     BIO *out;
1087db522d3aSSimon L. B. Nielsen 
1088db522d3aSSimon L. B. Nielsen     if (!ctx || (ctx->debug_level < level) || (!ctx->debug_file))
1089db522d3aSSimon L. B. Nielsen         return;
1090db522d3aSSimon L. B. Nielsen     out = BIO_new_file(ctx->debug_file, "a+");
1091e71b7053SJung-uk Kim     if (out == NULL) {
1092e71b7053SJung-uk Kim         CAPIerr(CAPI_F_CAPI_VTRACE, CAPI_R_FILE_OPEN_ERROR);
1093e71b7053SJung-uk Kim         return;
1094e71b7053SJung-uk Kim     }
1095db522d3aSSimon L. B. Nielsen     BIO_vprintf(out, format, argptr);
1096db522d3aSSimon L. B. Nielsen     BIO_free(out);
1097db522d3aSSimon L. B. Nielsen }
1098db522d3aSSimon L. B. Nielsen 
CAPI_trace(CAPI_CTX * ctx,char * format,...)1099db522d3aSSimon L. B. Nielsen static void CAPI_trace(CAPI_CTX *ctx, char *format, ...)
1100db522d3aSSimon L. B. Nielsen {
1101db522d3aSSimon L. B. Nielsen     va_list args;
1102db522d3aSSimon L. B. Nielsen     va_start(args, format);
1103db522d3aSSimon L. B. Nielsen     capi_vtrace(ctx, CAPI_DBG_TRACE, format, args);
1104db522d3aSSimon L. B. Nielsen     va_end(args);
1105db522d3aSSimon L. B. Nielsen }
1106db522d3aSSimon L. B. Nielsen 
capi_addlasterror(void)1107db522d3aSSimon L. B. Nielsen static void capi_addlasterror(void)
1108db522d3aSSimon L. B. Nielsen {
1109db522d3aSSimon L. B. Nielsen     capi_adderror(GetLastError());
1110db522d3aSSimon L. B. Nielsen }
1111db522d3aSSimon L. B. Nielsen 
capi_adderror(DWORD err)1112db522d3aSSimon L. B. Nielsen static void capi_adderror(DWORD err)
1113db522d3aSSimon L. B. Nielsen {
1114db522d3aSSimon L. B. Nielsen     char errstr[10];
1115db522d3aSSimon L. B. Nielsen     BIO_snprintf(errstr, 10, "%lX", err);
1116db522d3aSSimon L. B. Nielsen     ERR_add_error_data(2, "Error code= 0x", errstr);
1117db522d3aSSimon L. B. Nielsen }
1118db522d3aSSimon L. B. Nielsen 
wide_to_asc(LPCWSTR wstr)11197bded2dbSJung-uk Kim static char *wide_to_asc(LPCWSTR wstr)
1120db522d3aSSimon L. B. Nielsen {
1121db522d3aSSimon L. B. Nielsen     char *str;
11226a599222SSimon L. B. Nielsen     int len_0, sz;
1123*b077aed3SPierre Pronchery     size_t len_1;
11246a599222SSimon L. B. Nielsen 
1125db522d3aSSimon L. B. Nielsen     if (!wstr)
1126db522d3aSSimon L. B. Nielsen         return NULL;
1127*b077aed3SPierre Pronchery 
1128*b077aed3SPierre Pronchery     len_1 = wcslen(wstr) + 1;
1129*b077aed3SPierre Pronchery 
1130*b077aed3SPierre Pronchery     if (len_1 > INT_MAX) {
1131*b077aed3SPierre Pronchery 	    CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_FUNCTION_NOT_SUPPORTED);
1132*b077aed3SPierre Pronchery 	    return NULL;
1133*b077aed3SPierre Pronchery     }
1134*b077aed3SPierre Pronchery 
1135*b077aed3SPierre Pronchery     len_0 = (int)len_1; /* WideCharToMultiByte expects int */
11366a599222SSimon L. B. Nielsen     sz = WideCharToMultiByte(CP_ACP, 0, wstr, len_0, NULL, 0, NULL, NULL);
11376f9291ceSJung-uk Kim     if (!sz) {
11386a599222SSimon L. B. Nielsen         CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_WIN32_ERROR);
11396a599222SSimon L. B. Nielsen         return NULL;
11406a599222SSimon L. B. Nielsen     }
11416a599222SSimon L. B. Nielsen     str = OPENSSL_malloc(sz);
1142e71b7053SJung-uk Kim     if (str == NULL) {
1143db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_WIDE_TO_ASC, ERR_R_MALLOC_FAILURE);
1144db522d3aSSimon L. B. Nielsen         return NULL;
1145db522d3aSSimon L. B. Nielsen     }
11466f9291ceSJung-uk Kim     if (!WideCharToMultiByte(CP_ACP, 0, wstr, len_0, str, sz, NULL, NULL)) {
11476a599222SSimon L. B. Nielsen         OPENSSL_free(str);
11486a599222SSimon L. B. Nielsen         CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_WIN32_ERROR);
11496a599222SSimon L. B. Nielsen         return NULL;
11506a599222SSimon L. B. Nielsen     }
1151db522d3aSSimon L. B. Nielsen     return str;
1152db522d3aSSimon L. B. Nielsen }
1153db522d3aSSimon L. B. Nielsen 
capi_get_provname(CAPI_CTX * ctx,LPSTR * pname,DWORD * ptype,DWORD idx)11546f9291ceSJung-uk Kim static int capi_get_provname(CAPI_CTX *ctx, LPSTR *pname, DWORD *ptype,
11556f9291ceSJung-uk Kim                              DWORD idx)
1156db522d3aSSimon L. B. Nielsen {
1157db522d3aSSimon L. B. Nielsen     DWORD len, err;
11587bded2dbSJung-uk Kim     LPTSTR name;
1159db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "capi_get_provname, index=%d\n", idx);
11607bded2dbSJung-uk Kim     if (!CryptEnumProviders(idx, NULL, 0, ptype, NULL, &len)) {
1161db522d3aSSimon L. B. Nielsen         err = GetLastError();
1162db522d3aSSimon L. B. Nielsen         if (err == ERROR_NO_MORE_ITEMS)
1163db522d3aSSimon L. B. Nielsen             return 2;
1164db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_PROVNAME, CAPI_R_CRYPTENUMPROVIDERS_ERROR);
1165db522d3aSSimon L. B. Nielsen         capi_adderror(err);
1166db522d3aSSimon L. B. Nielsen         return 0;
1167db522d3aSSimon L. B. Nielsen     }
1168db522d3aSSimon L. B. Nielsen     name = OPENSSL_malloc(len);
1169aeb5019cSJung-uk Kim     if (name == NULL) {
1170aeb5019cSJung-uk Kim         CAPIerr(CAPI_F_CAPI_GET_PROVNAME, ERR_R_MALLOC_FAILURE);
1171aeb5019cSJung-uk Kim         return 0;
1172aeb5019cSJung-uk Kim     }
11737bded2dbSJung-uk Kim     if (!CryptEnumProviders(idx, NULL, 0, ptype, name, &len)) {
1174db522d3aSSimon L. B. Nielsen         err = GetLastError();
1175e71b7053SJung-uk Kim         OPENSSL_free(name);
1176db522d3aSSimon L. B. Nielsen         if (err == ERROR_NO_MORE_ITEMS)
1177db522d3aSSimon L. B. Nielsen             return 2;
1178db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_PROVNAME, CAPI_R_CRYPTENUMPROVIDERS_ERROR);
1179db522d3aSSimon L. B. Nielsen         capi_adderror(err);
1180db522d3aSSimon L. B. Nielsen         return 0;
1181db522d3aSSimon L. B. Nielsen     }
1182e71b7053SJung-uk Kim     if (sizeof(TCHAR) != sizeof(char)) {
11837bded2dbSJung-uk Kim         *pname = wide_to_asc((WCHAR *)name);
1184e71b7053SJung-uk Kim         OPENSSL_free(name);
1185e71b7053SJung-uk Kim         if (*pname == NULL)
1186e71b7053SJung-uk Kim             return 0;
1187e71b7053SJung-uk Kim     } else {
11887bded2dbSJung-uk Kim         *pname = (char *)name;
1189e71b7053SJung-uk Kim     }
11907bded2dbSJung-uk Kim     CAPI_trace(ctx, "capi_get_provname, returned name=%s, type=%d\n", *pname,
11916f9291ceSJung-uk Kim                *ptype);
1192db522d3aSSimon L. B. Nielsen 
1193db522d3aSSimon L. B. Nielsen     return 1;
1194db522d3aSSimon L. B. Nielsen }
1195db522d3aSSimon L. B. Nielsen 
capi_list_providers(CAPI_CTX * ctx,BIO * out)1196db522d3aSSimon L. B. Nielsen static int capi_list_providers(CAPI_CTX *ctx, BIO *out)
1197db522d3aSSimon L. B. Nielsen {
1198db522d3aSSimon L. B. Nielsen     DWORD idx, ptype;
1199db522d3aSSimon L. B. Nielsen     int ret;
12006a599222SSimon L. B. Nielsen     LPSTR provname = NULL;
1201db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "capi_list_providers\n");
1202db522d3aSSimon L. B. Nielsen     BIO_printf(out, "Available CSPs:\n");
12036f9291ceSJung-uk Kim     for (idx = 0;; idx++) {
1204db522d3aSSimon L. B. Nielsen         ret = capi_get_provname(ctx, &provname, &ptype, idx);
1205db522d3aSSimon L. B. Nielsen         if (ret == 2)
1206db522d3aSSimon L. B. Nielsen             break;
1207db522d3aSSimon L. B. Nielsen         if (ret == 0)
1208db522d3aSSimon L. B. Nielsen             break;
1209e71b7053SJung-uk Kim         BIO_printf(out, "%lu. %s, type %lu\n", idx, provname, ptype);
1210db522d3aSSimon L. B. Nielsen         OPENSSL_free(provname);
1211db522d3aSSimon L. B. Nielsen     }
1212db522d3aSSimon L. B. Nielsen     return 1;
1213db522d3aSSimon L. B. Nielsen }
1214db522d3aSSimon L. B. Nielsen 
capi_list_containers(CAPI_CTX * ctx,BIO * out)1215db522d3aSSimon L. B. Nielsen static int capi_list_containers(CAPI_CTX *ctx, BIO *out)
1216db522d3aSSimon L. B. Nielsen {
1217db522d3aSSimon L. B. Nielsen     int ret = 1;
1218db522d3aSSimon L. B. Nielsen     HCRYPTPROV hprov;
1219db522d3aSSimon L. B. Nielsen     DWORD err, idx, flags, buflen = 0, clen;
1220db522d3aSSimon L. B. Nielsen     LPSTR cname;
1221e71b7053SJung-uk Kim     LPWSTR cspname = NULL;
12227bded2dbSJung-uk Kim 
12236f9291ceSJung-uk Kim     CAPI_trace(ctx, "Listing containers CSP=%s, type = %d\n", ctx->cspname,
12246f9291ceSJung-uk Kim                ctx->csptype);
1225e71b7053SJung-uk Kim     if (ctx->cspname != NULL) {
1226e71b7053SJung-uk Kim         if ((clen = MultiByteToWideChar(CP_ACP, 0, ctx->cspname, -1,
1227e71b7053SJung-uk Kim                                         NULL, 0))) {
12287bded2dbSJung-uk Kim             cspname = alloca(clen * sizeof(WCHAR));
12297bded2dbSJung-uk Kim             MultiByteToWideChar(CP_ACP, 0, ctx->cspname, -1, (WCHAR *)cspname,
12307bded2dbSJung-uk Kim                                 clen);
12317bded2dbSJung-uk Kim         }
1232e71b7053SJung-uk Kim         if (cspname == NULL) {
12337bded2dbSJung-uk Kim             CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, ERR_R_MALLOC_FAILURE);
12347bded2dbSJung-uk Kim             capi_addlasterror();
12357bded2dbSJung-uk Kim             return 0;
12367bded2dbSJung-uk Kim         }
1237e71b7053SJung-uk Kim     }
1238e71b7053SJung-uk Kim     if (!CryptAcquireContextW(&hprov, NULL, cspname, ctx->csptype,
1239e71b7053SJung-uk Kim                               CRYPT_VERIFYCONTEXT)) {
12406f9291ceSJung-uk Kim         CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS,
12416f9291ceSJung-uk Kim                 CAPI_R_CRYPTACQUIRECONTEXT_ERROR);
1242db522d3aSSimon L. B. Nielsen         capi_addlasterror();
1243db522d3aSSimon L. B. Nielsen         return 0;
1244db522d3aSSimon L. B. Nielsen     }
1245e71b7053SJung-uk Kim     if (!CryptGetProvParam(hprov, PP_ENUMCONTAINERS, NULL, &buflen,
1246e71b7053SJung-uk Kim                            CRYPT_FIRST)) {
1247db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_ENUMCONTAINERS_ERROR);
1248db522d3aSSimon L. B. Nielsen         capi_addlasterror();
124912de4ed2SJung-uk Kim         CryptReleaseContext(hprov, 0);
1250db522d3aSSimon L. B. Nielsen         return 0;
1251db522d3aSSimon L. B. Nielsen     }
1252db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "Got max container len %d\n", buflen);
1253db522d3aSSimon L. B. Nielsen     if (buflen == 0)
1254db522d3aSSimon L. B. Nielsen         buflen = 1024;
1255db522d3aSSimon L. B. Nielsen     cname = OPENSSL_malloc(buflen);
1256e71b7053SJung-uk Kim     if (cname == NULL) {
1257db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, ERR_R_MALLOC_FAILURE);
1258db522d3aSSimon L. B. Nielsen         goto err;
1259db522d3aSSimon L. B. Nielsen     }
1260db522d3aSSimon L. B. Nielsen 
12616f9291ceSJung-uk Kim     for (idx = 0;; idx++) {
1262db522d3aSSimon L. B. Nielsen         clen = buflen;
1263db522d3aSSimon L. B. Nielsen         cname[0] = 0;
1264db522d3aSSimon L. B. Nielsen 
1265db522d3aSSimon L. B. Nielsen         if (idx == 0)
1266db522d3aSSimon L. B. Nielsen             flags = CRYPT_FIRST;
1267db522d3aSSimon L. B. Nielsen         else
1268db522d3aSSimon L. B. Nielsen             flags = 0;
1269e71b7053SJung-uk Kim         if (!CryptGetProvParam(hprov, PP_ENUMCONTAINERS, (BYTE *)cname,
1270e71b7053SJung-uk Kim                                &clen, flags)) {
1271db522d3aSSimon L. B. Nielsen             err = GetLastError();
1272db522d3aSSimon L. B. Nielsen             if (err == ERROR_NO_MORE_ITEMS)
1273db522d3aSSimon L. B. Nielsen                 goto done;
1274db522d3aSSimon L. B. Nielsen             CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_ENUMCONTAINERS_ERROR);
1275db522d3aSSimon L. B. Nielsen             capi_adderror(err);
1276db522d3aSSimon L. B. Nielsen             goto err;
1277db522d3aSSimon L. B. Nielsen         }
12786f9291ceSJung-uk Kim         CAPI_trace(ctx, "Container name %s, len=%d, index=%d, flags=%d\n",
12796f9291ceSJung-uk Kim                    cname, clen, idx, flags);
12806f9291ceSJung-uk Kim         if (!cname[0] && (clen == buflen)) {
1281db522d3aSSimon L. B. Nielsen             CAPI_trace(ctx, "Enumerate bug: using workaround\n");
1282db522d3aSSimon L. B. Nielsen             goto done;
1283db522d3aSSimon L. B. Nielsen         }
1284e71b7053SJung-uk Kim         BIO_printf(out, "%lu. %s\n", idx, cname);
1285db522d3aSSimon L. B. Nielsen     }
1286db522d3aSSimon L. B. Nielsen  err:
1287db522d3aSSimon L. B. Nielsen 
1288db522d3aSSimon L. B. Nielsen     ret = 0;
1289db522d3aSSimon L. B. Nielsen 
1290db522d3aSSimon L. B. Nielsen  done:
1291db522d3aSSimon L. B. Nielsen     OPENSSL_free(cname);
1292db522d3aSSimon L. B. Nielsen     CryptReleaseContext(hprov, 0);
1293db522d3aSSimon L. B. Nielsen 
1294db522d3aSSimon L. B. Nielsen     return ret;
1295db522d3aSSimon L. B. Nielsen }
1296db522d3aSSimon L. B. Nielsen 
capi_get_prov_info(CAPI_CTX * ctx,PCCERT_CONTEXT cert)1297e71b7053SJung-uk Kim static CRYPT_KEY_PROV_INFO *capi_get_prov_info(CAPI_CTX *ctx,
1298e71b7053SJung-uk Kim                                                PCCERT_CONTEXT cert)
1299db522d3aSSimon L. B. Nielsen {
1300db522d3aSSimon L. B. Nielsen     DWORD len;
1301db522d3aSSimon L. B. Nielsen     CRYPT_KEY_PROV_INFO *pinfo;
1302db522d3aSSimon L. B. Nielsen 
1303e71b7053SJung-uk Kim     if (!CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID,
1304e71b7053SJung-uk Kim                                            NULL, &len))
1305db522d3aSSimon L. B. Nielsen         return NULL;
1306db522d3aSSimon L. B. Nielsen     pinfo = OPENSSL_malloc(len);
1307e71b7053SJung-uk Kim     if (pinfo == NULL) {
1308db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_PROV_INFO, ERR_R_MALLOC_FAILURE);
1309db522d3aSSimon L. B. Nielsen         return NULL;
1310db522d3aSSimon L. B. Nielsen     }
1311e71b7053SJung-uk Kim     if (!CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID,
1312e71b7053SJung-uk Kim                                            pinfo, &len)) {
13136f9291ceSJung-uk Kim         CAPIerr(CAPI_F_CAPI_GET_PROV_INFO,
13146f9291ceSJung-uk Kim                 CAPI_R_ERROR_GETTING_KEY_PROVIDER_INFO);
1315db522d3aSSimon L. B. Nielsen         capi_addlasterror();
1316db522d3aSSimon L. B. Nielsen         OPENSSL_free(pinfo);
1317db522d3aSSimon L. B. Nielsen         return NULL;
1318db522d3aSSimon L. B. Nielsen     }
1319db522d3aSSimon L. B. Nielsen     return pinfo;
1320db522d3aSSimon L. B. Nielsen }
1321db522d3aSSimon L. B. Nielsen 
capi_dump_prov_info(CAPI_CTX * ctx,BIO * out,CRYPT_KEY_PROV_INFO * pinfo)13226f9291ceSJung-uk Kim static void capi_dump_prov_info(CAPI_CTX *ctx, BIO *out,
13236f9291ceSJung-uk Kim                                 CRYPT_KEY_PROV_INFO *pinfo)
1324db522d3aSSimon L. B. Nielsen {
1325db522d3aSSimon L. B. Nielsen     char *provname = NULL, *contname = NULL;
1326*b077aed3SPierre Pronchery 
1327*b077aed3SPierre Pronchery     if (pinfo == NULL) {
1328db522d3aSSimon L. B. Nielsen         BIO_printf(out, "  No Private Key\n");
1329db522d3aSSimon L. B. Nielsen         return;
1330db522d3aSSimon L. B. Nielsen     }
1331db522d3aSSimon L. B. Nielsen     provname = wide_to_asc(pinfo->pwszProvName);
1332db522d3aSSimon L. B. Nielsen     contname = wide_to_asc(pinfo->pwszContainerName);
1333*b077aed3SPierre Pronchery     if (provname == NULL || contname == NULL)
1334db522d3aSSimon L. B. Nielsen         goto err;
1335db522d3aSSimon L. B. Nielsen 
1336db522d3aSSimon L. B. Nielsen     BIO_printf(out, "  Private Key Info:\n");
1337e71b7053SJung-uk Kim     BIO_printf(out, "    Provider Name:  %s, Provider Type %lu\n", provname,
13386f9291ceSJung-uk Kim                pinfo->dwProvType);
1339e71b7053SJung-uk Kim     BIO_printf(out, "    Container Name: %s, Key Type %lu\n", contname,
13406f9291ceSJung-uk Kim                pinfo->dwKeySpec);
1341db522d3aSSimon L. B. Nielsen  err:
1342db522d3aSSimon L. B. Nielsen     OPENSSL_free(provname);
1343db522d3aSSimon L. B. Nielsen     OPENSSL_free(contname);
1344db522d3aSSimon L. B. Nielsen }
1345db522d3aSSimon L. B. Nielsen 
capi_cert_get_fname(CAPI_CTX * ctx,PCCERT_CONTEXT cert)1346e71b7053SJung-uk Kim static char *capi_cert_get_fname(CAPI_CTX *ctx, PCCERT_CONTEXT cert)
1347db522d3aSSimon L. B. Nielsen {
1348db522d3aSSimon L. B. Nielsen     LPWSTR wfname;
1349db522d3aSSimon L. B. Nielsen     DWORD dlen;
1350db522d3aSSimon L. B. Nielsen 
1351db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "capi_cert_get_fname\n");
1352e71b7053SJung-uk Kim     if (!CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID,
1353e71b7053SJung-uk Kim                                            NULL, &dlen))
1354db522d3aSSimon L. B. Nielsen         return NULL;
1355db522d3aSSimon L. B. Nielsen     wfname = OPENSSL_malloc(dlen);
1356e71b7053SJung-uk Kim     if (wfname == NULL)
1357aeb5019cSJung-uk Kim         return NULL;
1358e71b7053SJung-uk Kim     if (CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID,
1359e71b7053SJung-uk Kim                                           wfname, &dlen)) {
1360db522d3aSSimon L. B. Nielsen         char *fname = wide_to_asc(wfname);
1361db522d3aSSimon L. B. Nielsen         OPENSSL_free(wfname);
1362db522d3aSSimon L. B. Nielsen         return fname;
1363db522d3aSSimon L. B. Nielsen     }
1364db522d3aSSimon L. B. Nielsen     CAPIerr(CAPI_F_CAPI_CERT_GET_FNAME, CAPI_R_ERROR_GETTING_FRIENDLY_NAME);
1365db522d3aSSimon L. B. Nielsen     capi_addlasterror();
1366db522d3aSSimon L. B. Nielsen 
1367db522d3aSSimon L. B. Nielsen     OPENSSL_free(wfname);
1368db522d3aSSimon L. B. Nielsen     return NULL;
1369db522d3aSSimon L. B. Nielsen }
1370db522d3aSSimon L. B. Nielsen 
capi_dump_cert(CAPI_CTX * ctx,BIO * out,PCCERT_CONTEXT cert)1371e71b7053SJung-uk Kim static void capi_dump_cert(CAPI_CTX *ctx, BIO *out, PCCERT_CONTEXT cert)
1372db522d3aSSimon L. B. Nielsen {
1373db522d3aSSimon L. B. Nielsen     X509 *x;
1374e71b7053SJung-uk Kim     const unsigned char *p;
1375db522d3aSSimon L. B. Nielsen     unsigned long flags = ctx->dump_flags;
13766f9291ceSJung-uk Kim     if (flags & CAPI_DMP_FNAME) {
1377db522d3aSSimon L. B. Nielsen         char *fname;
1378db522d3aSSimon L. B. Nielsen         fname = capi_cert_get_fname(ctx, cert);
13796f9291ceSJung-uk Kim         if (fname) {
1380db522d3aSSimon L. B. Nielsen             BIO_printf(out, "  Friendly Name \"%s\"\n", fname);
1381db522d3aSSimon L. B. Nielsen             OPENSSL_free(fname);
1382e71b7053SJung-uk Kim         } else {
1383db522d3aSSimon L. B. Nielsen             BIO_printf(out, "  <No Friendly Name>\n");
1384db522d3aSSimon L. B. Nielsen         }
1385e71b7053SJung-uk Kim     }
1386db522d3aSSimon L. B. Nielsen 
1387db522d3aSSimon L. B. Nielsen     p = cert->pbCertEncoded;
1388db522d3aSSimon L. B. Nielsen     x = d2i_X509(NULL, &p, cert->cbCertEncoded);
1389db522d3aSSimon L. B. Nielsen     if (!x)
1390db522d3aSSimon L. B. Nielsen         BIO_printf(out, "  <Can't parse certificate>\n");
13916f9291ceSJung-uk Kim     if (flags & CAPI_DMP_SUMMARY) {
1392db522d3aSSimon L. B. Nielsen         BIO_printf(out, "  Subject: ");
1393db522d3aSSimon L. B. Nielsen         X509_NAME_print_ex(out, X509_get_subject_name(x), 0, XN_FLAG_ONELINE);
1394db522d3aSSimon L. B. Nielsen         BIO_printf(out, "\n  Issuer: ");
1395db522d3aSSimon L. B. Nielsen         X509_NAME_print_ex(out, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE);
1396db522d3aSSimon L. B. Nielsen         BIO_printf(out, "\n");
1397db522d3aSSimon L. B. Nielsen     }
1398db522d3aSSimon L. B. Nielsen     if (flags & CAPI_DMP_FULL)
1399db522d3aSSimon L. B. Nielsen         X509_print_ex(out, x, XN_FLAG_ONELINE, 0);
1400db522d3aSSimon L. B. Nielsen 
14016f9291ceSJung-uk Kim     if (flags & CAPI_DMP_PKEYINFO) {
1402db522d3aSSimon L. B. Nielsen         CRYPT_KEY_PROV_INFO *pinfo;
1403db522d3aSSimon L. B. Nielsen         pinfo = capi_get_prov_info(ctx, cert);
1404db522d3aSSimon L. B. Nielsen         capi_dump_prov_info(ctx, out, pinfo);
1405db522d3aSSimon L. B. Nielsen         OPENSSL_free(pinfo);
1406db522d3aSSimon L. B. Nielsen     }
1407db522d3aSSimon L. B. Nielsen 
1408db522d3aSSimon L. B. Nielsen     if (flags & CAPI_DMP_PEM)
1409db522d3aSSimon L. B. Nielsen         PEM_write_bio_X509(out, x);
1410db522d3aSSimon L. B. Nielsen     X509_free(x);
1411db522d3aSSimon L. B. Nielsen }
1412db522d3aSSimon L. B. Nielsen 
capi_open_store(CAPI_CTX * ctx,char * storename)1413e71b7053SJung-uk Kim static HCERTSTORE capi_open_store(CAPI_CTX *ctx, char *storename)
1414db522d3aSSimon L. B. Nielsen {
1415db522d3aSSimon L. B. Nielsen     HCERTSTORE hstore;
1416db522d3aSSimon L. B. Nielsen 
1417db522d3aSSimon L. B. Nielsen     if (!storename)
1418db522d3aSSimon L. B. Nielsen         storename = ctx->storename;
1419db522d3aSSimon L. B. Nielsen     if (!storename)
1420db522d3aSSimon L. B. Nielsen         storename = "MY";
1421db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "Opening certificate store %s\n", storename);
1422db522d3aSSimon L. B. Nielsen 
1423db522d3aSSimon L. B. Nielsen     hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0,
1424db522d3aSSimon L. B. Nielsen                            ctx->store_flags, storename);
14256f9291ceSJung-uk Kim     if (!hstore) {
1426db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_OPEN_STORE, CAPI_R_ERROR_OPENING_STORE);
1427db522d3aSSimon L. B. Nielsen         capi_addlasterror();
1428db522d3aSSimon L. B. Nielsen     }
1429db522d3aSSimon L. B. Nielsen     return hstore;
1430db522d3aSSimon L. B. Nielsen }
1431db522d3aSSimon L. B. Nielsen 
capi_list_certs(CAPI_CTX * ctx,BIO * out,char * id)1432db522d3aSSimon L. B. Nielsen int capi_list_certs(CAPI_CTX *ctx, BIO *out, char *id)
1433db522d3aSSimon L. B. Nielsen {
1434db522d3aSSimon L. B. Nielsen     char *storename;
1435db522d3aSSimon L. B. Nielsen     int idx;
1436db522d3aSSimon L. B. Nielsen     int ret = 1;
1437db522d3aSSimon L. B. Nielsen     HCERTSTORE hstore;
1438db522d3aSSimon L. B. Nielsen     PCCERT_CONTEXT cert = NULL;
1439db522d3aSSimon L. B. Nielsen 
1440db522d3aSSimon L. B. Nielsen     storename = ctx->storename;
1441db522d3aSSimon L. B. Nielsen     if (!storename)
1442db522d3aSSimon L. B. Nielsen         storename = "MY";
1443db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "Listing certs for store %s\n", storename);
1444db522d3aSSimon L. B. Nielsen 
1445db522d3aSSimon L. B. Nielsen     hstore = capi_open_store(ctx, storename);
1446db522d3aSSimon L. B. Nielsen     if (!hstore)
1447db522d3aSSimon L. B. Nielsen         return 0;
14486f9291ceSJung-uk Kim     if (id) {
1449db522d3aSSimon L. B. Nielsen         cert = capi_find_cert(ctx, id, hstore);
14506f9291ceSJung-uk Kim         if (!cert) {
1451db522d3aSSimon L. B. Nielsen             ret = 0;
1452db522d3aSSimon L. B. Nielsen             goto err;
1453db522d3aSSimon L. B. Nielsen         }
1454db522d3aSSimon L. B. Nielsen         capi_dump_cert(ctx, out, cert);
1455db522d3aSSimon L. B. Nielsen         CertFreeCertificateContext(cert);
14566f9291ceSJung-uk Kim     } else {
14576f9291ceSJung-uk Kim         for (idx = 0;; idx++) {
1458db522d3aSSimon L. B. Nielsen             cert = CertEnumCertificatesInStore(hstore, cert);
1459db522d3aSSimon L. B. Nielsen             if (!cert)
1460db522d3aSSimon L. B. Nielsen                 break;
1461db522d3aSSimon L. B. Nielsen             BIO_printf(out, "Certificate %d\n", idx);
1462db522d3aSSimon L. B. Nielsen             capi_dump_cert(ctx, out, cert);
1463db522d3aSSimon L. B. Nielsen         }
1464db522d3aSSimon L. B. Nielsen     }
1465db522d3aSSimon L. B. Nielsen  err:
1466db522d3aSSimon L. B. Nielsen     CertCloseStore(hstore, 0);
1467db522d3aSSimon L. B. Nielsen     return ret;
1468db522d3aSSimon L. B. Nielsen }
1469db522d3aSSimon L. B. Nielsen 
capi_find_cert(CAPI_CTX * ctx,const char * id,HCERTSTORE hstore)14706f9291ceSJung-uk Kim static PCCERT_CONTEXT capi_find_cert(CAPI_CTX *ctx, const char *id,
14716f9291ceSJung-uk Kim                                      HCERTSTORE hstore)
1472db522d3aSSimon L. B. Nielsen {
1473db522d3aSSimon L. B. Nielsen     PCCERT_CONTEXT cert = NULL;
1474db522d3aSSimon L. B. Nielsen     char *fname = NULL;
1475db522d3aSSimon L. B. Nielsen     int match;
14766f9291ceSJung-uk Kim     switch (ctx->lookup_method) {
1477db522d3aSSimon L. B. Nielsen     case CAPI_LU_SUBSTR:
1478e71b7053SJung-uk Kim         return CertFindCertificateInStore(hstore, X509_ASN_ENCODING, 0,
1479db522d3aSSimon L. B. Nielsen                                           CERT_FIND_SUBJECT_STR_A, id, NULL);
1480db522d3aSSimon L. B. Nielsen     case CAPI_LU_FNAME:
14816f9291ceSJung-uk Kim         for (;;) {
1482db522d3aSSimon L. B. Nielsen             cert = CertEnumCertificatesInStore(hstore, cert);
1483db522d3aSSimon L. B. Nielsen             if (!cert)
1484db522d3aSSimon L. B. Nielsen                 return NULL;
1485db522d3aSSimon L. B. Nielsen             fname = capi_cert_get_fname(ctx, cert);
14866f9291ceSJung-uk Kim             if (fname) {
1487db522d3aSSimon L. B. Nielsen                 if (strcmp(fname, id))
1488db522d3aSSimon L. B. Nielsen                     match = 0;
1489db522d3aSSimon L. B. Nielsen                 else
1490db522d3aSSimon L. B. Nielsen                     match = 1;
1491db522d3aSSimon L. B. Nielsen                 OPENSSL_free(fname);
1492db522d3aSSimon L. B. Nielsen                 if (match)
1493db522d3aSSimon L. B. Nielsen                     return cert;
1494db522d3aSSimon L. B. Nielsen             }
1495db522d3aSSimon L. B. Nielsen         }
1496db522d3aSSimon L. B. Nielsen     default:
1497db522d3aSSimon L. B. Nielsen         return NULL;
1498db522d3aSSimon L. B. Nielsen     }
1499db522d3aSSimon L. B. Nielsen }
1500db522d3aSSimon L. B. Nielsen 
capi_get_key(CAPI_CTX * ctx,const WCHAR * contname,const WCHAR * provname,DWORD ptype,DWORD keyspec)1501e71b7053SJung-uk Kim static CAPI_KEY *capi_get_key(CAPI_CTX *ctx, const WCHAR *contname,
1502e71b7053SJung-uk Kim                               const WCHAR *provname, DWORD ptype,
1503e71b7053SJung-uk Kim                               DWORD keyspec)
1504db522d3aSSimon L. B. Nielsen {
150509286989SJung-uk Kim     DWORD dwFlags = 0;
1506e71b7053SJung-uk Kim     CAPI_KEY *key = OPENSSL_malloc(sizeof(*key));
1507e71b7053SJung-uk Kim 
1508e71b7053SJung-uk Kim     if (key == NULL)
1509e71b7053SJung-uk Kim         return NULL;
1510e71b7053SJung-uk Kim     /* If PROV_RSA_AES supported use it instead */
1511e71b7053SJung-uk Kim     if (ptype == PROV_RSA_FULL && use_aes_csp &&
1512e71b7053SJung-uk Kim         wcscmp(provname, rsa_enh_cspname) == 0) {
1513e71b7053SJung-uk Kim         provname = rsa_aes_cspname;
1514e71b7053SJung-uk Kim         ptype = PROV_RSA_AES;
1515aeb5019cSJung-uk Kim     }
1516e71b7053SJung-uk Kim     if (ctx && ctx->debug_level >= CAPI_DBG_TRACE && ctx->debug_file) {
1517e71b7053SJung-uk Kim         /*
1518e71b7053SJung-uk Kim          * above 'if' is [complementary] copy from CAPI_trace and serves
1519e71b7053SJung-uk Kim          * as optimization to minimize [below] malloc-ations
1520e71b7053SJung-uk Kim          */
1521e71b7053SJung-uk Kim         char *_contname = wide_to_asc(contname);
1522e71b7053SJung-uk Kim         char *_provname = wide_to_asc(provname);
15237bded2dbSJung-uk Kim 
15247bded2dbSJung-uk Kim         CAPI_trace(ctx, "capi_get_key, contname=%s, provname=%s, type=%d\n",
15257bded2dbSJung-uk Kim                    _contname, _provname, ptype);
15267bded2dbSJung-uk Kim         OPENSSL_free(_provname);
15277bded2dbSJung-uk Kim         OPENSSL_free(_contname);
15287bded2dbSJung-uk Kim     }
152909286989SJung-uk Kim     if (ctx->store_flags & CERT_SYSTEM_STORE_LOCAL_MACHINE)
153009286989SJung-uk Kim         dwFlags = CRYPT_MACHINE_KEYSET;
1531e71b7053SJung-uk Kim     if (!CryptAcquireContextW(&key->hprov, contname, provname, ptype,
1532e71b7053SJung-uk Kim                               dwFlags)) {
1533db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_CRYPTACQUIRECONTEXT_ERROR);
1534db522d3aSSimon L. B. Nielsen         capi_addlasterror();
1535db522d3aSSimon L. B. Nielsen         goto err;
1536db522d3aSSimon L. B. Nielsen     }
15376f9291ceSJung-uk Kim     if (!CryptGetUserKey(key->hprov, keyspec, &key->key)) {
1538db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_GETUSERKEY_ERROR);
1539db522d3aSSimon L. B. Nielsen         capi_addlasterror();
1540db522d3aSSimon L. B. Nielsen         CryptReleaseContext(key->hprov, 0);
1541db522d3aSSimon L. B. Nielsen         goto err;
1542db522d3aSSimon L. B. Nielsen     }
1543db522d3aSSimon L. B. Nielsen     key->keyspec = keyspec;
1544db522d3aSSimon L. B. Nielsen     key->pcert = NULL;
1545db522d3aSSimon L. B. Nielsen     return key;
1546db522d3aSSimon L. B. Nielsen 
1547db522d3aSSimon L. B. Nielsen  err:
1548db522d3aSSimon L. B. Nielsen     OPENSSL_free(key);
1549db522d3aSSimon L. B. Nielsen     return NULL;
1550db522d3aSSimon L. B. Nielsen }
1551db522d3aSSimon L. B. Nielsen 
capi_get_cert_key(CAPI_CTX * ctx,PCCERT_CONTEXT cert)1552db522d3aSSimon L. B. Nielsen static CAPI_KEY *capi_get_cert_key(CAPI_CTX *ctx, PCCERT_CONTEXT cert)
1553db522d3aSSimon L. B. Nielsen {
1554db522d3aSSimon L. B. Nielsen     CAPI_KEY *key = NULL;
1555db522d3aSSimon L. B. Nielsen     CRYPT_KEY_PROV_INFO *pinfo = NULL;
1556db522d3aSSimon L. B. Nielsen 
1557e71b7053SJung-uk Kim     pinfo = capi_get_prov_info(ctx, cert);
1558e71b7053SJung-uk Kim 
1559e71b7053SJung-uk Kim     if (pinfo != NULL)
1560e71b7053SJung-uk Kim         key = capi_get_key(ctx, pinfo->pwszContainerName, pinfo->pwszProvName,
1561e71b7053SJung-uk Kim                            pinfo->dwProvType, pinfo->dwKeySpec);
1562e71b7053SJung-uk Kim 
1563db522d3aSSimon L. B. Nielsen     OPENSSL_free(pinfo);
1564db522d3aSSimon L. B. Nielsen     return key;
1565db522d3aSSimon L. B. Nielsen }
1566db522d3aSSimon L. B. Nielsen 
capi_find_key(CAPI_CTX * ctx,const char * id)1567db522d3aSSimon L. B. Nielsen CAPI_KEY *capi_find_key(CAPI_CTX *ctx, const char *id)
1568db522d3aSSimon L. B. Nielsen {
1569db522d3aSSimon L. B. Nielsen     PCCERT_CONTEXT cert;
1570db522d3aSSimon L. B. Nielsen     HCERTSTORE hstore;
1571db522d3aSSimon L. B. Nielsen     CAPI_KEY *key = NULL;
1572e71b7053SJung-uk Kim 
15736f9291ceSJung-uk Kim     switch (ctx->lookup_method) {
1574db522d3aSSimon L. B. Nielsen     case CAPI_LU_SUBSTR:
1575db522d3aSSimon L. B. Nielsen     case CAPI_LU_FNAME:
1576db522d3aSSimon L. B. Nielsen         hstore = capi_open_store(ctx, NULL);
1577db522d3aSSimon L. B. Nielsen         if (!hstore)
1578db522d3aSSimon L. B. Nielsen             return NULL;
1579db522d3aSSimon L. B. Nielsen         cert = capi_find_cert(ctx, id, hstore);
15806f9291ceSJung-uk Kim         if (cert) {
1581db522d3aSSimon L. B. Nielsen             key = capi_get_cert_key(ctx, cert);
1582db522d3aSSimon L. B. Nielsen             CertFreeCertificateContext(cert);
1583db522d3aSSimon L. B. Nielsen         }
1584db522d3aSSimon L. B. Nielsen         CertCloseStore(hstore, 0);
1585db522d3aSSimon L. B. Nielsen         break;
1586db522d3aSSimon L. B. Nielsen 
1587db522d3aSSimon L. B. Nielsen     case CAPI_LU_CONTNAME:
1588e71b7053SJung-uk Kim         {
15897bded2dbSJung-uk Kim             WCHAR *contname, *provname;
15907bded2dbSJung-uk Kim             DWORD len;
15917bded2dbSJung-uk Kim 
15927bded2dbSJung-uk Kim             if ((len = MultiByteToWideChar(CP_ACP, 0, id, -1, NULL, 0)) &&
15937bded2dbSJung-uk Kim                 (contname = alloca(len * sizeof(WCHAR)),
15947bded2dbSJung-uk Kim                  MultiByteToWideChar(CP_ACP, 0, id, -1, contname, len)) &&
1595e71b7053SJung-uk Kim                 (len = MultiByteToWideChar(CP_ACP, 0, ctx->cspname, -1,
1596e71b7053SJung-uk Kim                                            NULL, 0)) &&
1597e71b7053SJung-uk Kim                 (provname = alloca(len * sizeof(WCHAR)),
1598e71b7053SJung-uk Kim                  MultiByteToWideChar(CP_ACP, 0, ctx->cspname, -1,
1599e71b7053SJung-uk Kim                                      provname, len)))
1600e71b7053SJung-uk Kim                 key = capi_get_key(ctx, contname, provname,
16017bded2dbSJung-uk Kim                                    ctx->csptype, ctx->keytype);
1602e71b7053SJung-uk Kim         }
1603db522d3aSSimon L. B. Nielsen         break;
1604db522d3aSSimon L. B. Nielsen     }
1605db522d3aSSimon L. B. Nielsen 
1606db522d3aSSimon L. B. Nielsen     return key;
1607db522d3aSSimon L. B. Nielsen }
1608db522d3aSSimon L. B. Nielsen 
capi_free_key(CAPI_KEY * key)1609db522d3aSSimon L. B. Nielsen void capi_free_key(CAPI_KEY *key)
1610db522d3aSSimon L. B. Nielsen {
1611db522d3aSSimon L. B. Nielsen     if (!key)
1612db522d3aSSimon L. B. Nielsen         return;
1613db522d3aSSimon L. B. Nielsen     CryptDestroyKey(key->key);
1614db522d3aSSimon L. B. Nielsen     CryptReleaseContext(key->hprov, 0);
1615db522d3aSSimon L. B. Nielsen     if (key->pcert)
1616db522d3aSSimon L. B. Nielsen         CertFreeCertificateContext(key->pcert);
1617db522d3aSSimon L. B. Nielsen     OPENSSL_free(key);
1618db522d3aSSimon L. B. Nielsen }
1619db522d3aSSimon L. B. Nielsen 
1620db522d3aSSimon L. B. Nielsen /* Initialize a CAPI_CTX structure */
1621db522d3aSSimon L. B. Nielsen 
capi_ctx_new(void)1622e71b7053SJung-uk Kim static CAPI_CTX *capi_ctx_new(void)
1623db522d3aSSimon L. B. Nielsen {
1624e71b7053SJung-uk Kim     CAPI_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
1625e71b7053SJung-uk Kim 
1626e71b7053SJung-uk Kim     if (ctx == NULL) {
1627db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CAPI_CTX_NEW, ERR_R_MALLOC_FAILURE);
1628db522d3aSSimon L. B. Nielsen         return NULL;
1629db522d3aSSimon L. B. Nielsen     }
1630db522d3aSSimon L. B. Nielsen     ctx->csptype = PROV_RSA_FULL;
1631db522d3aSSimon L. B. Nielsen     ctx->dump_flags = CAPI_DMP_SUMMARY | CAPI_DMP_FNAME;
1632db522d3aSSimon L. B. Nielsen     ctx->keytype = AT_KEYEXCHANGE;
1633db522d3aSSimon L. B. Nielsen     ctx->store_flags = CERT_STORE_OPEN_EXISTING_FLAG |
16346f9291ceSJung-uk Kim         CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_CURRENT_USER;
1635db522d3aSSimon L. B. Nielsen     ctx->lookup_method = CAPI_LU_SUBSTR;
1636db522d3aSSimon L. B. Nielsen     ctx->client_cert_select = cert_select_simple;
1637db522d3aSSimon L. B. Nielsen     return ctx;
1638db522d3aSSimon L. B. Nielsen }
1639db522d3aSSimon L. B. Nielsen 
capi_ctx_free(CAPI_CTX * ctx)1640db522d3aSSimon L. B. Nielsen static void capi_ctx_free(CAPI_CTX *ctx)
1641db522d3aSSimon L. B. Nielsen {
1642db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "Calling capi_ctx_free with %lx\n", ctx);
1643db522d3aSSimon L. B. Nielsen     if (!ctx)
1644db522d3aSSimon L. B. Nielsen         return;
1645db522d3aSSimon L. B. Nielsen     OPENSSL_free(ctx->cspname);
1646db522d3aSSimon L. B. Nielsen     OPENSSL_free(ctx->debug_file);
1647db522d3aSSimon L. B. Nielsen     OPENSSL_free(ctx->storename);
1648db522d3aSSimon L. B. Nielsen     OPENSSL_free(ctx->ssl_client_store);
1649db522d3aSSimon L. B. Nielsen     OPENSSL_free(ctx);
1650db522d3aSSimon L. B. Nielsen }
1651db522d3aSSimon L. B. Nielsen 
capi_ctx_set_provname(CAPI_CTX * ctx,LPSTR pname,DWORD type,int check)16526f9291ceSJung-uk Kim static int capi_ctx_set_provname(CAPI_CTX *ctx, LPSTR pname, DWORD type,
16536f9291ceSJung-uk Kim                                  int check)
1654db522d3aSSimon L. B. Nielsen {
1655e71b7053SJung-uk Kim     LPSTR tmpcspname;
1656e71b7053SJung-uk Kim 
1657db522d3aSSimon L. B. Nielsen     CAPI_trace(ctx, "capi_ctx_set_provname, name=%s, type=%d\n", pname, type);
16586f9291ceSJung-uk Kim     if (check) {
1659db522d3aSSimon L. B. Nielsen         HCRYPTPROV hprov;
1660e71b7053SJung-uk Kim         LPWSTR name = NULL;
16617bded2dbSJung-uk Kim         DWORD len;
1662e71b7053SJung-uk Kim 
16637bded2dbSJung-uk Kim         if ((len = MultiByteToWideChar(CP_ACP, 0, pname, -1, NULL, 0))) {
16647bded2dbSJung-uk Kim             name = alloca(len * sizeof(WCHAR));
16657bded2dbSJung-uk Kim             MultiByteToWideChar(CP_ACP, 0, pname, -1, (WCHAR *)name, len);
16667bded2dbSJung-uk Kim         }
1667e71b7053SJung-uk Kim         if (name == NULL || !CryptAcquireContextW(&hprov, NULL, name, type,
16686f9291ceSJung-uk Kim                                                   CRYPT_VERIFYCONTEXT)) {
16696f9291ceSJung-uk Kim             CAPIerr(CAPI_F_CAPI_CTX_SET_PROVNAME,
16706f9291ceSJung-uk Kim                     CAPI_R_CRYPTACQUIRECONTEXT_ERROR);
1671db522d3aSSimon L. B. Nielsen             capi_addlasterror();
1672db522d3aSSimon L. B. Nielsen             return 0;
1673db522d3aSSimon L. B. Nielsen         }
1674db522d3aSSimon L. B. Nielsen         CryptReleaseContext(hprov, 0);
1675db522d3aSSimon L. B. Nielsen     }
1676e71b7053SJung-uk Kim     tmpcspname = OPENSSL_strdup(pname);
1677e71b7053SJung-uk Kim     if (tmpcspname == NULL) {
1678e71b7053SJung-uk Kim         CAPIerr(CAPI_F_CAPI_CTX_SET_PROVNAME, ERR_R_MALLOC_FAILURE);
1679e71b7053SJung-uk Kim         return 0;
1680e71b7053SJung-uk Kim     }
168112de4ed2SJung-uk Kim     OPENSSL_free(ctx->cspname);
1682e71b7053SJung-uk Kim     ctx->cspname = tmpcspname;
1683db522d3aSSimon L. B. Nielsen     ctx->csptype = type;
1684db522d3aSSimon L. B. Nielsen     return 1;
1685db522d3aSSimon L. B. Nielsen }
1686db522d3aSSimon L. B. Nielsen 
capi_ctx_set_provname_idx(CAPI_CTX * ctx,int idx)1687db522d3aSSimon L. B. Nielsen static int capi_ctx_set_provname_idx(CAPI_CTX *ctx, int idx)
1688db522d3aSSimon L. B. Nielsen {
1689db522d3aSSimon L. B. Nielsen     LPSTR pname;
1690db522d3aSSimon L. B. Nielsen     DWORD type;
169112de4ed2SJung-uk Kim     int res;
1692db522d3aSSimon L. B. Nielsen     if (capi_get_provname(ctx, &pname, &type, idx) != 1)
1693db522d3aSSimon L. B. Nielsen         return 0;
169412de4ed2SJung-uk Kim     res = capi_ctx_set_provname(ctx, pname, type, 0);
169512de4ed2SJung-uk Kim     OPENSSL_free(pname);
169612de4ed2SJung-uk Kim     return res;
1697db522d3aSSimon L. B. Nielsen }
1698db522d3aSSimon L. B. Nielsen 
cert_issuer_match(STACK_OF (X509_NAME)* ca_dn,X509 * x)1699db522d3aSSimon L. B. Nielsen static int cert_issuer_match(STACK_OF(X509_NAME) *ca_dn, X509 *x)
1700db522d3aSSimon L. B. Nielsen {
1701db522d3aSSimon L. B. Nielsen     int i;
1702db522d3aSSimon L. B. Nielsen     X509_NAME *nm;
1703db522d3aSSimon L. B. Nielsen     /* Special case: empty list: match anything */
1704db522d3aSSimon L. B. Nielsen     if (sk_X509_NAME_num(ca_dn) <= 0)
1705db522d3aSSimon L. B. Nielsen         return 1;
17066f9291ceSJung-uk Kim     for (i = 0; i < sk_X509_NAME_num(ca_dn); i++) {
1707db522d3aSSimon L. B. Nielsen         nm = sk_X509_NAME_value(ca_dn, i);
1708db522d3aSSimon L. B. Nielsen         if (!X509_NAME_cmp(nm, X509_get_issuer_name(x)))
1709db522d3aSSimon L. B. Nielsen             return 1;
1710db522d3aSSimon L. B. Nielsen     }
1711db522d3aSSimon L. B. Nielsen     return 0;
1712db522d3aSSimon L. B. Nielsen }
1713db522d3aSSimon L. B. Nielsen 
capi_load_ssl_client_cert(ENGINE * e,SSL * ssl,STACK_OF (X509_NAME)* ca_dn,X509 ** pcert,EVP_PKEY ** pkey,STACK_OF (X509)** pother,UI_METHOD * ui_method,void * callback_data)1714db522d3aSSimon L. B. Nielsen static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl,
17156f9291ceSJung-uk Kim                                      STACK_OF(X509_NAME) *ca_dn, X509 **pcert,
17166f9291ceSJung-uk Kim                                      EVP_PKEY **pkey, STACK_OF(X509) **pother,
17176f9291ceSJung-uk Kim                                      UI_METHOD *ui_method,
17186f9291ceSJung-uk Kim                                      void *callback_data)
1719db522d3aSSimon L. B. Nielsen {
1720db522d3aSSimon L. B. Nielsen     STACK_OF(X509) *certs = NULL;
1721db522d3aSSimon L. B. Nielsen     X509 *x;
1722db522d3aSSimon L. B. Nielsen     char *storename;
1723e71b7053SJung-uk Kim     const unsigned char *p;
1724db522d3aSSimon L. B. Nielsen     int i, client_cert_idx;
1725db522d3aSSimon L. B. Nielsen     HCERTSTORE hstore;
1726db522d3aSSimon L. B. Nielsen     PCCERT_CONTEXT cert = NULL, excert = NULL;
1727db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
1728db522d3aSSimon L. B. Nielsen     CAPI_KEY *key;
1729db522d3aSSimon L. B. Nielsen     ctx = ENGINE_get_ex_data(e, capi_idx);
1730db522d3aSSimon L. B. Nielsen 
1731db522d3aSSimon L. B. Nielsen     *pcert = NULL;
1732db522d3aSSimon L. B. Nielsen     *pkey = NULL;
1733db522d3aSSimon L. B. Nielsen 
1734db522d3aSSimon L. B. Nielsen     storename = ctx->ssl_client_store;
1735db522d3aSSimon L. B. Nielsen     if (!storename)
1736db522d3aSSimon L. B. Nielsen         storename = "MY";
1737db522d3aSSimon L. B. Nielsen 
1738db522d3aSSimon L. B. Nielsen     hstore = capi_open_store(ctx, storename);
1739db522d3aSSimon L. B. Nielsen     if (!hstore)
1740db522d3aSSimon L. B. Nielsen         return 0;
1741db522d3aSSimon L. B. Nielsen     /* Enumerate all certificates collect any matches */
17426f9291ceSJung-uk Kim     for (i = 0;; i++) {
1743db522d3aSSimon L. B. Nielsen         cert = CertEnumCertificatesInStore(hstore, cert);
1744db522d3aSSimon L. B. Nielsen         if (!cert)
1745db522d3aSSimon L. B. Nielsen             break;
1746db522d3aSSimon L. B. Nielsen         p = cert->pbCertEncoded;
1747db522d3aSSimon L. B. Nielsen         x = d2i_X509(NULL, &p, cert->cbCertEncoded);
17486f9291ceSJung-uk Kim         if (!x) {
1749db522d3aSSimon L. B. Nielsen             CAPI_trace(ctx, "Can't Parse Certificate %d\n", i);
1750db522d3aSSimon L. B. Nielsen             continue;
1751db522d3aSSimon L. B. Nielsen         }
1752db522d3aSSimon L. B. Nielsen         if (cert_issuer_match(ca_dn, x)
17536f9291ceSJung-uk Kim             && X509_check_purpose(x, X509_PURPOSE_SSL_CLIENT, 0)) {
1754db522d3aSSimon L. B. Nielsen             key = capi_get_cert_key(ctx, cert);
17556f9291ceSJung-uk Kim             if (!key) {
1756db522d3aSSimon L. B. Nielsen                 X509_free(x);
1757db522d3aSSimon L. B. Nielsen                 continue;
1758db522d3aSSimon L. B. Nielsen             }
17596f9291ceSJung-uk Kim             /*
17606f9291ceSJung-uk Kim              * Match found: attach extra data to it so we can retrieve the
17616f9291ceSJung-uk Kim              * key later.
1762db522d3aSSimon L. B. Nielsen              */
1763db522d3aSSimon L. B. Nielsen             excert = CertDuplicateCertificateContext(cert);
1764db522d3aSSimon L. B. Nielsen             key->pcert = excert;
1765db522d3aSSimon L. B. Nielsen             X509_set_ex_data(x, cert_capi_idx, key);
1766db522d3aSSimon L. B. Nielsen 
1767db522d3aSSimon L. B. Nielsen             if (!certs)
1768db522d3aSSimon L. B. Nielsen                 certs = sk_X509_new_null();
1769db522d3aSSimon L. B. Nielsen 
1770db522d3aSSimon L. B. Nielsen             sk_X509_push(certs, x);
1771e71b7053SJung-uk Kim         } else {
1772db522d3aSSimon L. B. Nielsen             X509_free(x);
1773e71b7053SJung-uk Kim         }
1774db522d3aSSimon L. B. Nielsen     }
1775db522d3aSSimon L. B. Nielsen 
1776db522d3aSSimon L. B. Nielsen     if (cert)
1777db522d3aSSimon L. B. Nielsen         CertFreeCertificateContext(cert);
1778db522d3aSSimon L. B. Nielsen     if (hstore)
1779db522d3aSSimon L. B. Nielsen         CertCloseStore(hstore, 0);
1780db522d3aSSimon L. B. Nielsen 
1781db522d3aSSimon L. B. Nielsen     if (!certs)
1782db522d3aSSimon L. B. Nielsen         return 0;
1783db522d3aSSimon L. B. Nielsen 
1784db522d3aSSimon L. B. Nielsen     /* Select the appropriate certificate */
1785db522d3aSSimon L. B. Nielsen 
1786db522d3aSSimon L. B. Nielsen     client_cert_idx = ctx->client_cert_select(e, ssl, certs);
1787db522d3aSSimon L. B. Nielsen 
1788db522d3aSSimon L. B. Nielsen     /* Set the selected certificate and free the rest */
1789db522d3aSSimon L. B. Nielsen 
17906f9291ceSJung-uk Kim     for (i = 0; i < sk_X509_num(certs); i++) {
1791db522d3aSSimon L. B. Nielsen         x = sk_X509_value(certs, i);
1792db522d3aSSimon L. B. Nielsen         if (i == client_cert_idx)
1793db522d3aSSimon L. B. Nielsen             *pcert = x;
17946f9291ceSJung-uk Kim         else {
1795db522d3aSSimon L. B. Nielsen             key = X509_get_ex_data(x, cert_capi_idx);
1796db522d3aSSimon L. B. Nielsen             capi_free_key(key);
1797db522d3aSSimon L. B. Nielsen             X509_free(x);
1798db522d3aSSimon L. B. Nielsen         }
1799db522d3aSSimon L. B. Nielsen     }
1800db522d3aSSimon L. B. Nielsen 
1801db522d3aSSimon L. B. Nielsen     sk_X509_free(certs);
1802db522d3aSSimon L. B. Nielsen 
1803*b077aed3SPierre Pronchery     if (*pcert == NULL)
1804db522d3aSSimon L. B. Nielsen         return 0;
1805db522d3aSSimon L. B. Nielsen 
1806db522d3aSSimon L. B. Nielsen     /* Setup key for selected certificate */
1807db522d3aSSimon L. B. Nielsen 
1808db522d3aSSimon L. B. Nielsen     key = X509_get_ex_data(*pcert, cert_capi_idx);
1809db522d3aSSimon L. B. Nielsen     *pkey = capi_get_pkey(e, key);
1810db522d3aSSimon L. B. Nielsen     X509_set_ex_data(*pcert, cert_capi_idx, NULL);
1811db522d3aSSimon L. B. Nielsen 
1812db522d3aSSimon L. B. Nielsen     return 1;
1813db522d3aSSimon L. B. Nielsen 
1814db522d3aSSimon L. B. Nielsen }
1815db522d3aSSimon L. B. Nielsen 
1816db522d3aSSimon L. B. Nielsen /* Simple client cert selection function: always select first */
1817db522d3aSSimon L. B. Nielsen 
cert_select_simple(ENGINE * e,SSL * ssl,STACK_OF (X509)* certs)1818db522d3aSSimon L. B. Nielsen static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs)
1819db522d3aSSimon L. B. Nielsen {
1820db522d3aSSimon L. B. Nielsen     return 0;
1821db522d3aSSimon L. B. Nielsen }
1822db522d3aSSimon L. B. Nielsen 
1823db522d3aSSimon L. B. Nielsen # ifdef OPENSSL_CAPIENG_DIALOG
1824db522d3aSSimon L. B. Nielsen 
18256f9291ceSJung-uk Kim /*
18266f9291ceSJung-uk Kim  * More complex cert selection function, using standard function
1827db522d3aSSimon L. B. Nielsen  * CryptUIDlgSelectCertificateFromStore() to produce a dialog box.
1828db522d3aSSimon L. B. Nielsen  */
1829db522d3aSSimon L. B. Nielsen 
18306f9291ceSJung-uk Kim /*
18316f9291ceSJung-uk Kim  * Definitions which are in cryptuiapi.h but this is not present in older
1832db522d3aSSimon L. B. Nielsen  * versions of headers.
1833db522d3aSSimon L. B. Nielsen  */
1834db522d3aSSimon L. B. Nielsen 
1835db522d3aSSimon L. B. Nielsen #  ifndef CRYPTUI_SELECT_LOCATION_COLUMN
1836db522d3aSSimon L. B. Nielsen #   define CRYPTUI_SELECT_LOCATION_COLUMN                   0x000000010
1837db522d3aSSimon L. B. Nielsen #   define CRYPTUI_SELECT_INTENDEDUSE_COLUMN                0x000000004
1838db522d3aSSimon L. B. Nielsen #  endif
1839db522d3aSSimon L. B. Nielsen 
1840db522d3aSSimon L. B. Nielsen #  define dlg_title L"OpenSSL Application SSL Client Certificate Selection"
1841db522d3aSSimon L. B. Nielsen #  define dlg_prompt L"Select a certificate to use for authentication"
1842db522d3aSSimon L. B. Nielsen #  define dlg_columns      CRYPTUI_SELECT_LOCATION_COLUMN \
1843db522d3aSSimon L. B. Nielsen                         |CRYPTUI_SELECT_INTENDEDUSE_COLUMN
1844db522d3aSSimon L. B. Nielsen 
cert_select_dialog(ENGINE * e,SSL * ssl,STACK_OF (X509)* certs)1845db522d3aSSimon L. B. Nielsen static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs)
1846db522d3aSSimon L. B. Nielsen {
1847db522d3aSSimon L. B. Nielsen     X509 *x;
1848db522d3aSSimon L. B. Nielsen     HCERTSTORE dstore;
1849db522d3aSSimon L. B. Nielsen     PCCERT_CONTEXT cert;
1850db522d3aSSimon L. B. Nielsen     CAPI_CTX *ctx;
1851db522d3aSSimon L. B. Nielsen     CAPI_KEY *key;
1852db522d3aSSimon L. B. Nielsen     HWND hwnd;
1853db522d3aSSimon L. B. Nielsen     int i, idx = -1;
1854db522d3aSSimon L. B. Nielsen     if (sk_X509_num(certs) == 1)
1855db522d3aSSimon L. B. Nielsen         return 0;
1856db522d3aSSimon L. B. Nielsen     ctx = ENGINE_get_ex_data(e, capi_idx);
1857db522d3aSSimon L. B. Nielsen     /* Create an in memory store of certificates */
1858db522d3aSSimon L. B. Nielsen     dstore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1859db522d3aSSimon L. B. Nielsen                            CERT_STORE_CREATE_NEW_FLAG, NULL);
18606f9291ceSJung-uk Kim     if (!dstore) {
1861db522d3aSSimon L. B. Nielsen         CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_CREATING_STORE);
1862db522d3aSSimon L. B. Nielsen         capi_addlasterror();
1863db522d3aSSimon L. B. Nielsen         goto err;
1864db522d3aSSimon L. B. Nielsen     }
1865db522d3aSSimon L. B. Nielsen     /* Add all certificates to store */
18666f9291ceSJung-uk Kim     for (i = 0; i < sk_X509_num(certs); i++) {
1867db522d3aSSimon L. B. Nielsen         x = sk_X509_value(certs, i);
1868db522d3aSSimon L. B. Nielsen         key = X509_get_ex_data(x, cert_capi_idx);
1869db522d3aSSimon L. B. Nielsen 
1870db522d3aSSimon L. B. Nielsen         if (!CertAddCertificateContextToStore(dstore, key->pcert,
18716f9291ceSJung-uk Kim                                               CERT_STORE_ADD_NEW, NULL)) {
1872db522d3aSSimon L. B. Nielsen             CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_ADDING_CERT);
1873db522d3aSSimon L. B. Nielsen             capi_addlasterror();
1874db522d3aSSimon L. B. Nielsen             goto err;
1875db522d3aSSimon L. B. Nielsen         }
1876db522d3aSSimon L. B. Nielsen 
1877db522d3aSSimon L. B. Nielsen     }
1878db522d3aSSimon L. B. Nielsen     hwnd = GetForegroundWindow();
1879db522d3aSSimon L. B. Nielsen     if (!hwnd)
1880db522d3aSSimon L. B. Nielsen         hwnd = GetActiveWindow();
1881db522d3aSSimon L. B. Nielsen     if (!hwnd && ctx->getconswindow)
1882db522d3aSSimon L. B. Nielsen         hwnd = ctx->getconswindow();
1883db522d3aSSimon L. B. Nielsen     /* Call dialog to select one */
1884db522d3aSSimon L. B. Nielsen     cert = ctx->certselectdlg(dstore, hwnd, dlg_title, dlg_prompt,
1885db522d3aSSimon L. B. Nielsen                               dlg_columns, 0, NULL);
1886db522d3aSSimon L. B. Nielsen 
1887db522d3aSSimon L. B. Nielsen     /* Find matching cert from list */
18886f9291ceSJung-uk Kim     if (cert) {
18896f9291ceSJung-uk Kim         for (i = 0; i < sk_X509_num(certs); i++) {
1890db522d3aSSimon L. B. Nielsen             x = sk_X509_value(certs, i);
1891db522d3aSSimon L. B. Nielsen             key = X509_get_ex_data(x, cert_capi_idx);
18926f9291ceSJung-uk Kim             if (CertCompareCertificate
18936f9291ceSJung-uk Kim                 (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, cert->pCertInfo,
18946f9291ceSJung-uk Kim                  key->pcert->pCertInfo)) {
1895db522d3aSSimon L. B. Nielsen                 idx = i;
1896db522d3aSSimon L. B. Nielsen                 break;
1897db522d3aSSimon L. B. Nielsen             }
1898db522d3aSSimon L. B. Nielsen         }
1899db522d3aSSimon L. B. Nielsen     }
1900db522d3aSSimon L. B. Nielsen 
1901db522d3aSSimon L. B. Nielsen  err:
1902db522d3aSSimon L. B. Nielsen     if (dstore)
1903db522d3aSSimon L. B. Nielsen         CertCloseStore(dstore, 0);
1904db522d3aSSimon L. B. Nielsen     return idx;
1905db522d3aSSimon L. B. Nielsen 
1906db522d3aSSimon L. B. Nielsen }
1907db522d3aSSimon L. B. Nielsen # endif
1908db522d3aSSimon L. B. Nielsen 
19091f13597dSJung-uk Kim #else                           /* !__COMPILE_CAPIENG */
1910db522d3aSSimon L. B. Nielsen # include <openssl/engine.h>
1911db522d3aSSimon L. B. Nielsen # ifndef OPENSSL_NO_DYNAMIC_ENGINE
1912db522d3aSSimon L. B. Nielsen OPENSSL_EXPORT
19131f13597dSJung-uk Kim     int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns);
19141f13597dSJung-uk Kim OPENSSL_EXPORT
bind_engine(ENGINE * e,const char * id,const dynamic_fns * fns)19156f9291ceSJung-uk Kim     int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns)
19166f9291ceSJung-uk Kim {
19176f9291ceSJung-uk Kim     return 0;
19186f9291ceSJung-uk Kim }
19196f9291ceSJung-uk Kim 
1920db522d3aSSimon L. B. Nielsen IMPLEMENT_DYNAMIC_CHECK_FN()
19211f13597dSJung-uk Kim # else
1922e71b7053SJung-uk Kim void engine_load_capi_int(void);
1923e71b7053SJung-uk Kim void engine_load_capi_int(void)
19246f9291ceSJung-uk Kim {
19256f9291ceSJung-uk Kim }
1926db522d3aSSimon L. B. Nielsen # endif
1927db522d3aSSimon L. B. Nielsen #endif
1928