OpenVPN
cryptoapi.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2004 Peter 'Luna' Runestig <peter@runestig.com>
3  * Copyright (c) 2018 Selva Nair <selva.nair@gmail.com>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without modifi-
7  * cation, are permitted provided that the following conditions are met:
8  *
9  * o Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * o Redistributions in binary form must reproduce the above copyright no-
13  * tice, this list of conditions and the following disclaimer in the do-
14  * cumentation and/or other materials provided with the distribution.
15  *
16  * o The names of the contributors may not be used to endorse or promote
17  * products derived from this software without specific prior written
18  * permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LI-
24  * ABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUEN-
25  * TIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEV-
27  * ER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABI-
28  * LITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
29  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #elif defined(_MSC_VER)
35 #include "config-msvc.h"
36 #endif
37 
38 #include "syshead.h"
39 
40 #ifdef ENABLE_CRYPTOAPI
41 
42 #include <openssl/ssl.h>
43 #include <openssl/evp.h>
44 #include <openssl/err.h>
45 #include <windows.h>
46 #include <wincrypt.h>
47 #include <ncrypt.h>
48 #include <stdio.h>
49 #include <ctype.h>
50 #include <assert.h>
51 
52 #include "buffer.h"
53 #include "openssl_compat.h"
54 #include "win32.h"
55 
56 /* MinGW w32api 3.17 is still incomplete when it comes to CryptoAPI while
57  * MinGW32-w64 defines all macros used. This is a hack around that problem.
58  */
59 #ifndef CERT_SYSTEM_STORE_LOCATION_SHIFT
60 #define CERT_SYSTEM_STORE_LOCATION_SHIFT 16
61 #endif
62 #ifndef CERT_SYSTEM_STORE_CURRENT_USER_ID
63 #define CERT_SYSTEM_STORE_CURRENT_USER_ID 1
64 #endif
65 #ifndef CERT_SYSTEM_STORE_CURRENT_USER
66 #define CERT_SYSTEM_STORE_CURRENT_USER (CERT_SYSTEM_STORE_CURRENT_USER_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT)
67 #endif
68 #ifndef CERT_STORE_READONLY_FLAG
69 #define CERT_STORE_READONLY_FLAG 0x00008000
70 #endif
71 #ifndef CERT_STORE_OPEN_EXISTING_FLAG
72 #define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000
73 #endif
74 
75 /* Size of an SSL signature: MD5+SHA1 */
76 #define SSL_SIG_LENGTH 36
77 
78 /* try to funnel any Windows/CryptoAPI error messages to OpenSSL ERR_... */
79 #define ERR_LIB_CRYPTOAPI (ERR_LIB_USER + 69) /* 69 is just a number... */
80 #define CRYPTOAPIerr(f) err_put_ms_error(GetLastError(), (f), __FILE__, __LINE__)
81 #define CRYPTOAPI_F_CERT_OPEN_SYSTEM_STORE 100
82 #define CRYPTOAPI_F_CERT_FIND_CERTIFICATE_IN_STORE 101
83 #define CRYPTOAPI_F_CRYPT_ACQUIRE_CERTIFICATE_PRIVATE_KEY 102
84 #define CRYPTOAPI_F_CRYPT_CREATE_HASH 103
85 #define CRYPTOAPI_F_CRYPT_GET_HASH_PARAM 104
86 #define CRYPTOAPI_F_CRYPT_SET_HASH_PARAM 105
87 #define CRYPTOAPI_F_CRYPT_SIGN_HASH 106
88 #define CRYPTOAPI_F_LOAD_LIBRARY 107
89 #define CRYPTOAPI_F_GET_PROC_ADDRESS 108
90 #define CRYPTOAPI_F_NCRYPT_SIGN_HASH 109
91 
92 static ERR_STRING_DATA CRYPTOAPI_str_functs[] = {
93  { ERR_PACK(ERR_LIB_CRYPTOAPI, 0, 0), "microsoft cryptoapi"},
94  { ERR_PACK(0, CRYPTOAPI_F_CERT_OPEN_SYSTEM_STORE, 0), "CertOpenSystemStore" },
95  { ERR_PACK(0, CRYPTOAPI_F_CERT_FIND_CERTIFICATE_IN_STORE, 0), "CertFindCertificateInStore" },
96  { ERR_PACK(0, CRYPTOAPI_F_CRYPT_ACQUIRE_CERTIFICATE_PRIVATE_KEY, 0), "CryptAcquireCertificatePrivateKey" },
97  { ERR_PACK(0, CRYPTOAPI_F_CRYPT_CREATE_HASH, 0), "CryptCreateHash" },
98  { ERR_PACK(0, CRYPTOAPI_F_CRYPT_GET_HASH_PARAM, 0), "CryptGetHashParam" },
99  { ERR_PACK(0, CRYPTOAPI_F_CRYPT_SET_HASH_PARAM, 0), "CryptSetHashParam" },
100  { ERR_PACK(0, CRYPTOAPI_F_CRYPT_SIGN_HASH, 0), "CryptSignHash" },
101  { ERR_PACK(0, CRYPTOAPI_F_LOAD_LIBRARY, 0), "LoadLibrary" },
102  { ERR_PACK(0, CRYPTOAPI_F_GET_PROC_ADDRESS, 0), "GetProcAddress" },
103  { ERR_PACK(0, CRYPTOAPI_F_NCRYPT_SIGN_HASH, 0), "NCryptSignHash" },
104  { 0, NULL }
105 };
106 
107 /* index for storing external data in EC_KEY: < 0 means uninitialized */
108 static int ec_data_idx = -1;
109 
110 /* Global EVP_PKEY_METHOD used to override the sign operation */
111 static EVP_PKEY_METHOD *pmethod;
112 static int (*default_pkey_sign_init) (EVP_PKEY_CTX *ctx);
113 static int (*default_pkey_sign) (EVP_PKEY_CTX *ctx, unsigned char *sig,
114  size_t *siglen, const unsigned char *tbs, size_t tbslen);
115 
116 typedef struct _CAPI_DATA {
117  const CERT_CONTEXT *cert_context;
118  HCRYPTPROV_OR_NCRYPT_KEY_HANDLE crypt_prov;
119  DWORD key_spec;
122 } CAPI_DATA;
123 
124 /* Translate OpenSSL padding type to CNG padding type
125  * Returns 0 for unknown/unsupported padding.
126  */
127 static DWORD
128 cng_padding_type(int padding)
129 {
130  DWORD pad = 0;
131 
132  switch (padding)
133  {
134  case RSA_NO_PADDING:
135  break;
136 
137  case RSA_PKCS1_PADDING:
138  pad = BCRYPT_PAD_PKCS1;
139  break;
140 
141  case RSA_PKCS1_PSS_PADDING:
142  pad = BCRYPT_PAD_PSS;
143  break;
144 
145  default:
146  msg(M_WARN|M_INFO, "cryptoapicert: unknown OpenSSL padding type %d.",
147  padding);
148  }
149 
150  return pad;
151 }
152 
153 /*
154  * Translate OpenSSL hash OID to CNG algorithm name. Returns
155  * "UNKNOWN" for unsupported algorithms and NULL for MD5+SHA1
156  * mixed hash used in TLS 1.1 and earlier.
157  */
158 static const wchar_t *
159 cng_hash_algo(int md_type)
160 {
161  const wchar_t *alg = L"UNKNOWN";
162  switch (md_type)
163  {
164  case NID_md5:
165  alg = BCRYPT_MD5_ALGORITHM;
166  break;
167 
168  case NID_sha1:
169  alg = BCRYPT_SHA1_ALGORITHM;
170  break;
171 
172  case NID_sha256:
173  alg = BCRYPT_SHA256_ALGORITHM;
174  break;
175 
176  case NID_sha384:
177  alg = BCRYPT_SHA384_ALGORITHM;
178  break;
179 
180  case NID_sha512:
181  alg = BCRYPT_SHA512_ALGORITHM;
182  break;
183 
184  case NID_md5_sha1:
185  case 0:
186  alg = NULL;
187  break;
188 
189  default:
190  msg(M_WARN|M_INFO, "cryptoapicert: Unknown hash type NID=0x%x", md_type);
191  break;
192  }
193  return alg;
194 }
195 
196 static void
198 {
199  if (!cd || cd->ref_count-- > 0)
200  {
201  return;
202  }
203  if (cd->free_crypt_prov && cd->crypt_prov)
204  {
205  if (cd->key_spec == CERT_NCRYPT_KEY_SPEC)
206  {
207  NCryptFreeObject(cd->crypt_prov);
208  }
209  else
210  {
211  CryptReleaseContext(cd->crypt_prov, 0);
212  }
213  }
214  if (cd->cert_context)
215  {
216  CertFreeCertificateContext(cd->cert_context);
217  }
218  free(cd);
219 }
220 
221 static char *
222 ms_error_text(DWORD ms_err)
223 {
224  LPVOID lpMsgBuf = NULL;
225  char *rv = NULL;
226 
227  FormatMessage(
228  FORMAT_MESSAGE_ALLOCATE_BUFFER
229  |FORMAT_MESSAGE_FROM_SYSTEM
230  |FORMAT_MESSAGE_IGNORE_INSERTS,
231  NULL, ms_err,
232  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
233  (LPTSTR) &lpMsgBuf, 0, NULL);
234  if (lpMsgBuf)
235  {
236  char *p;
237  rv = string_alloc(lpMsgBuf, NULL);
238  LocalFree(lpMsgBuf);
239  /* trim to the left */
240  if (rv)
241  {
242  for (p = rv + strlen(rv) - 1; p >= rv; p--)
243  {
244  if (isspace(*p))
245  {
246  *p = '\0';
247  }
248  else
249  {
250  break;
251  }
252  }
253  }
254  }
255  return rv;
256 }
257 
258 static void
259 err_put_ms_error(DWORD ms_err, int func, const char *file, int line)
260 {
261  static int init = 0;
262 #define ERR_MAP_SZ 16
263  static struct {
264  int err;
265  DWORD ms_err; /* I don't think we get more than 16 *different* errors */
266  } err_map[ERR_MAP_SZ]; /* in here, before we give up the whole thing... */
267  int i;
268 
269  if (ms_err == 0)
270  {
271  /* 0 is not an error */
272  return;
273  }
274  if (!init)
275  {
276  ERR_load_strings(ERR_LIB_CRYPTOAPI, CRYPTOAPI_str_functs);
277  memset(&err_map, 0, sizeof(err_map));
278  init++;
279  }
280  /* since MS error codes are 32 bit, and the ones in the ERR_... system is
281  * only 12, we must have a mapping table between them. */
282  for (i = 0; i < ERR_MAP_SZ; i++)
283  {
284  if (err_map[i].ms_err == ms_err)
285  {
286  ERR_PUT_error(ERR_LIB_CRYPTOAPI, func, err_map[i].err, file, line);
287  break;
288  }
289  else if (err_map[i].ms_err == 0)
290  {
291  /* end of table, add new entry */
292  ERR_STRING_DATA *esd = calloc(2, sizeof(*esd));
293  if (esd == NULL)
294  {
295  break;
296  }
297  err_map[i].ms_err = ms_err;
298  err_map[i].err = esd->error = i + 100;
299  esd->string = ms_error_text(ms_err);
300  check_malloc_return(esd->string);
301  ERR_load_strings(ERR_LIB_CRYPTOAPI, esd);
302  ERR_PUT_error(ERR_LIB_CRYPTOAPI, func, err_map[i].err, file, line);
303  break;
304  }
305  }
306 }
307 
308 /* encrypt */
309 static int
310 rsa_pub_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
311 {
312  /* I haven't been able to trigger this one, but I want to know if it happens... */
313  assert(0);
314 
315  return 0;
316 }
317 
318 /* verify arbitrary data */
319 static int
320 rsa_pub_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
321 {
322  /* I haven't been able to trigger this one, but I want to know if it happens... */
323  assert(0);
324 
325  return 0;
326 }
327 
340 static int
341 priv_enc_CNG(const CAPI_DATA *cd, const wchar_t *hash_algo, const unsigned char *from,
342  int flen, unsigned char *to, int tlen, DWORD padding, DWORD saltlen)
343 {
344  NCRYPT_KEY_HANDLE hkey = cd->crypt_prov;
345  DWORD len = 0;
346  ASSERT(cd->key_spec == CERT_NCRYPT_KEY_SPEC);
347 
348  DWORD status;
349 
350  msg(D_LOW, "Signing hash using CNG: data size = %d padding = %lu", flen, padding);
351 
352  if (padding == BCRYPT_PAD_PKCS1)
353  {
354  BCRYPT_PKCS1_PADDING_INFO padinfo = {hash_algo};
355  status = NCryptSignHash(hkey, &padinfo, (BYTE *)from, flen,
356  to, tlen, &len, padding);
357  }
358  else if (padding == BCRYPT_PAD_PSS)
359  {
360  BCRYPT_PSS_PADDING_INFO padinfo = {hash_algo, saltlen};
361  status = NCryptSignHash(hkey, &padinfo, (BYTE *)from, flen,
362  to, tlen, &len, padding);
363  }
364  else
365  {
366  RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
367  return 0;
368  }
369 
370  if (status != ERROR_SUCCESS)
371  {
372  SetLastError(status);
374  len = 0;
375  }
376 
377  /* Unlike CAPI, CNG signature is in big endian order. No reversing needed. */
378  return len;
379 }
380 
381 /* sign arbitrary data */
382 static int
383 rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
384 {
385  CAPI_DATA *cd = (CAPI_DATA *) RSA_meth_get0_app_data(RSA_get_method(rsa));
386  HCRYPTHASH hash;
387  DWORD hash_size, len, i;
388  unsigned char *buf;
389 
390  if (cd == NULL)
391  {
392  RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER);
393  return 0;
394  }
395 
396  if (padding != RSA_PKCS1_PADDING)
397  {
398  /* AFAICS, CryptSignHash() *always* uses PKCS1 padding. */
399  RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
400  return 0;
401  }
402 
403  if (cd->key_spec == CERT_NCRYPT_KEY_SPEC)
404  {
405  return priv_enc_CNG(cd, NULL, from, flen, to, RSA_size(rsa),
406  cng_padding_type(padding), 0);
407  }
408 
409  /* Unfortunately, there is no "CryptSign()" function in CryptoAPI, that would
410  * be way to straightforward for M$, I guess... So we have to do it this
411  * tricky way instead, by creating a "Hash", and load the already-made hash
412  * from 'from' into it. */
413  /* For now, we only support NID_md5_sha1 */
414  if (flen != SSL_SIG_LENGTH)
415  {
416  RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH);
417  return 0;
418  }
419  if (!CryptCreateHash(cd->crypt_prov, CALG_SSL3_SHAMD5, 0, 0, &hash))
420  {
422  return 0;
423  }
424  len = sizeof(hash_size);
425  if (!CryptGetHashParam(hash, HP_HASHSIZE, (BYTE *) &hash_size, &len, 0))
426  {
428  CryptDestroyHash(hash);
429  return 0;
430  }
431  if ((int) hash_size != flen)
432  {
433  RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH);
434  CryptDestroyHash(hash);
435  return 0;
436  }
437  if (!CryptSetHashParam(hash, HP_HASHVAL, (BYTE * ) from, 0))
438  {
440  CryptDestroyHash(hash);
441  return 0;
442  }
443 
444  len = RSA_size(rsa);
445  buf = malloc(len);
446  if (buf == NULL)
447  {
448  RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);
449  CryptDestroyHash(hash);
450  return 0;
451  }
452  if (!CryptSignHash(hash, cd->key_spec, NULL, 0, buf, &len))
453  {
455  CryptDestroyHash(hash);
456  free(buf);
457  return 0;
458  }
459  /* and now, we have to reverse the byte-order in the result from CryptSignHash()... */
460  for (i = 0; i < len; i++)
461  {
462  to[i] = buf[len - i - 1];
463  }
464  free(buf);
465 
466  CryptDestroyHash(hash);
467  return len;
468 }
469 
478 static int
479 rsa_sign_CNG(int type, const unsigned char *m, unsigned int m_len,
480  unsigned char *sig, unsigned int *siglen, const RSA *rsa)
481 {
482  CAPI_DATA *cd = (CAPI_DATA *) RSA_meth_get0_app_data(RSA_get_method(rsa));
483  const wchar_t *alg = NULL;
484  int padding = RSA_PKCS1_PADDING;
485 
486  *siglen = 0;
487  if (cd == NULL)
488  {
489  RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER);
490  return 0;
491  }
492 
493  alg = cng_hash_algo(type);
494  if (alg && wcscmp(alg, L"UNKNOWN") == 0)
495  {
496  RSAerr(RSA_F_RSA_SIGN, RSA_R_UNKNOWN_ALGORITHM_TYPE);
497  return 0;
498  }
499 
500  *siglen = priv_enc_CNG(cd, alg, m, (int)m_len, sig, RSA_size(rsa),
501  cng_padding_type(padding), 0);
502 
503  return (*siglen == 0) ? 0 : 1;
504 }
505 
506 /* decrypt */
507 static int
508 rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
509 {
510  /* I haven't been able to trigger this one, but I want to know if it happens... */
511  assert(0);
512 
513  return 0;
514 }
515 
516 /* called at RSA_new */
517 static int
518 init(RSA *rsa)
519 {
520 
521  return 0;
522 }
523 
524 /* called at RSA_free */
525 static int
526 finish(RSA *rsa)
527 {
528  const RSA_METHOD *rsa_meth = RSA_get_method(rsa);
529  CAPI_DATA *cd = (CAPI_DATA *) RSA_meth_get0_app_data(rsa_meth);
530 
531  if (cd == NULL)
532  {
533  return 0;
534  }
535  CAPI_DATA_free(cd);
536  RSA_meth_free((RSA_METHOD *) rsa_meth);
537  return 1;
538 }
539 
540 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(OPENSSL_NO_EC)
541 
542 static EC_KEY_METHOD *ec_method = NULL;
543 
545 static void
546 ec_finish(EC_KEY *ec)
547 {
548  EC_KEY_METHOD_free(ec_method);
549  ec_method = NULL;
550  CAPI_DATA *cd = EC_KEY_get_ex_data(ec, ec_data_idx);
551  CAPI_DATA_free(cd);
552  EC_KEY_set_ex_data(ec, ec_data_idx, NULL);
553 }
554 
556 static int
557 ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
558 {
559  return 1;
560 }
561 
568 static ECDSA_SIG *
569 ecdsa_bin2sig(unsigned char *buf, int len)
570 {
571  ECDSA_SIG *ecsig = NULL;
572  DWORD rlen = len/2;
573  BIGNUM *r = BN_bin2bn(buf, rlen, NULL);
574  BIGNUM *s = BN_bin2bn(buf+rlen, rlen, NULL);
575  if (!r || !s)
576  {
577  goto err;
578  }
579  ecsig = ECDSA_SIG_new(); /* in openssl 1.1 this does not allocate r, s */
580  if (!ecsig)
581  {
582  goto err;
583  }
584  if (!ECDSA_SIG_set0(ecsig, r, s)) /* ecsig takes ownership of r and s */
585  {
586  ECDSA_SIG_free(ecsig);
587  goto err;
588  }
589  return ecsig;
590 err:
591  BN_free(r); /* it is ok to free NULL BN */
592  BN_free(s);
593  return NULL;
594 }
595 
597 static ECDSA_SIG *
598 ecdsa_sign_sig(const unsigned char *dgst, int dgstlen,
599  const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *ec)
600 {
601  ECDSA_SIG *ecsig = NULL;
602  CAPI_DATA *cd = (CAPI_DATA *)EC_KEY_get_ex_data(ec, ec_data_idx);
603 
604  ASSERT(cd->key_spec == CERT_NCRYPT_KEY_SPEC);
605 
606  NCRYPT_KEY_HANDLE hkey = cd->crypt_prov;
607  BYTE buf[512]; /* large enough buffer for signature to avoid malloc */
608  DWORD len = _countof(buf);
609 
610  msg(D_LOW, "Cryptoapi: signing hash using EC key: data size = %d", dgstlen);
611 
612  DWORD status = NCryptSignHash(hkey, NULL, (BYTE *)dgst, dgstlen, (BYTE *)buf, len, &len, 0);
613  if (status != ERROR_SUCCESS)
614  {
615  SetLastError(status);
617  }
618  else
619  {
620  /* NCryptSignHash returns r, s concatenated in buf[] */
621  ecsig = ecdsa_bin2sig(buf, len);
622  }
623  return ecsig;
624 }
625 
627 static int
628 ecdsa_sign(int type, const unsigned char *dgst, int dgstlen, unsigned char *sig,
629  unsigned int *siglen, const BIGNUM *kinv, const BIGNUM *r, EC_KEY *ec)
630 {
631  ECDSA_SIG *s;
632 
633  *siglen = 0;
634  s = ecdsa_sign_sig(dgst, dgstlen, NULL, NULL, ec);
635  if (s == NULL)
636  {
637  return 0;
638  }
639 
640  /* convert internal signature structure 's' to DER encoded byte array in sig */
641  int len = i2d_ECDSA_SIG(s, NULL);
642  if (len > ECDSA_size(ec))
643  {
644  ECDSA_SIG_free(s);
645  msg(M_NONFATAL,"Error: DER encoded ECDSA signature is too long (%d bytes)", len);
646  return 0;
647  }
648  *siglen = i2d_ECDSA_SIG(s, &sig);
649  ECDSA_SIG_free(s);
650 
651  return 1;
652 }
653 
654 static int
655 ssl_ctx_set_eckey(SSL_CTX *ssl_ctx, CAPI_DATA *cd, EVP_PKEY *pkey)
656 {
657  EC_KEY *ec = NULL;
658  EVP_PKEY *privkey = NULL;
659 
660  if (cd->key_spec != CERT_NCRYPT_KEY_SPEC)
661  {
662  msg(M_NONFATAL, "ERROR: cryptoapicert with only legacy private key handle available."
663  " EC certificate not supported.");
664  goto err;
665  }
666  /* create a method struct with default callbacks filled in */
667  ec_method = EC_KEY_METHOD_new(EC_KEY_OpenSSL());
668  if (!ec_method)
669  {
670  goto err;
671  }
672 
673  /* We only need to set finish among init methods, and sign methods */
674  EC_KEY_METHOD_set_init(ec_method, NULL, ec_finish, NULL, NULL, NULL, NULL);
675  EC_KEY_METHOD_set_sign(ec_method, ecdsa_sign, ecdsa_sign_setup, ecdsa_sign_sig);
676 
677  ec = EC_KEY_dup(EVP_PKEY_get0_EC_KEY(pkey));
678  if (!ec)
679  {
680  goto err;
681  }
682  if (!EC_KEY_set_method(ec, ec_method))
683  {
684  goto err;
685  }
686 
687  /* get an index to store cd as external data */
688  if (ec_data_idx < 0)
689  {
690  ec_data_idx = EC_KEY_get_ex_new_index(0, "cryptapicert ec key", NULL, NULL, NULL);
691  if (ec_data_idx < 0)
692  {
693  goto err;
694  }
695  }
696  EC_KEY_set_ex_data(ec, ec_data_idx, cd);
697 
698  /* cd assigned to ec as ex_data, increase its refcount */
699  cd->ref_count++;
700 
701  privkey = EVP_PKEY_new();
702  if (!EVP_PKEY_assign_EC_KEY(privkey, ec))
703  {
704  EC_KEY_free(ec);
705  goto err;
706  }
707  /* from here on ec will get freed with privkey */
708 
709  if (!SSL_CTX_use_PrivateKey(ssl_ctx, privkey))
710  {
711  goto err;
712  }
713  EVP_PKEY_free(privkey); /* this will dn_ref or free ec as well */
714  return 1;
715 
716 err:
717  if (privkey)
718  {
719  EVP_PKEY_free(privkey);
720  }
721  else if (ec)
722  {
723  EC_KEY_free(ec);
724  }
725  if (ec_method) /* do always set ec_method = NULL after freeing it */
726  {
727  EC_KEY_METHOD_free(ec_method);
728  ec_method = NULL;
729  }
730  return 0;
731 }
732 
733 #endif /* OPENSSL_VERSION_NUMBER >= 1.1.0 */
734 
735 static const CERT_CONTEXT *
736 find_certificate_in_store(const char *cert_prop, HCERTSTORE cert_store)
737 {
738  /* Find, and use, the desired certificate from the store. The
739  * 'cert_prop' certificate search string can look like this:
740  * SUBJ:<certificate substring to match>
741  * THUMB:<certificate thumbprint hex value>, e.g.
742  * THUMB:f6 49 24 41 01 b4 fb 44 0c ce f4 36 ae d0 c4 c9 df 7a b6 28
743  * The first matching certificate that has not expired is returned.
744  */
745  const CERT_CONTEXT *rv = NULL;
746  DWORD find_type;
747  const void *find_param;
748  unsigned char hash[255];
749  CRYPT_HASH_BLOB blob = {.cbData = 0, .pbData = hash};
750  struct gc_arena gc = gc_new();
751 
752  if (!strncmp(cert_prop, "SUBJ:", 5))
753  {
754  /* skip the tag */
755  find_param = wide_string(cert_prop + 5, &gc);
756  find_type = CERT_FIND_SUBJECT_STR_W;
757  }
758  else if (!strncmp(cert_prop, "THUMB:", 6))
759  {
760  const char *p;
761  int i, x = 0;
762  find_type = CERT_FIND_HASH;
763  find_param = &blob;
764 
765  /* skip the tag */
766  cert_prop += 6;
767  for (p = cert_prop, i = 0; *p && i < sizeof(hash); i++)
768  {
769  if (*p >= '0' && *p <= '9')
770  {
771  x = (*p - '0') << 4;
772  }
773  else if (*p >= 'A' && *p <= 'F')
774  {
775  x = (*p - 'A' + 10) << 4;
776  }
777  else if (*p >= 'a' && *p <= 'f')
778  {
779  x = (*p - 'a' + 10) << 4;
780  }
781  if (!*++p) /* unexpected end of string */
782  {
783  msg(M_WARN, "WARNING: cryptoapicert: error parsing <THUMB:%s>.", cert_prop);
784  goto out;
785  }
786  if (*p >= '0' && *p <= '9')
787  {
788  x += *p - '0';
789  }
790  else if (*p >= 'A' && *p <= 'F')
791  {
792  x += *p - 'A' + 10;
793  }
794  else if (*p >= 'a' && *p <= 'f')
795  {
796  x += *p - 'a' + 10;
797  }
798  hash[i] = x;
799  /* skip any space(s) between hex numbers */
800  for (p++; *p && *p == ' '; p++)
801  {
802  }
803  }
804  blob.cbData = i;
805  }
806  else
807  {
808  msg(M_WARN, "WARNING: cryptoapicert: unsupported certificate specification <%s>", cert_prop);
809  goto out;
810  }
811 
812  while (true)
813  {
814  int validity = 1;
815  /* this frees previous rv, if not NULL */
816  rv = CertFindCertificateInStore(cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
817  0, find_type, find_param, rv);
818  if (rv)
819  {
820  validity = CertVerifyTimeValidity(NULL, rv->pCertInfo);
821  }
822  if (!rv || validity == 0)
823  {
824  break;
825  }
826  msg(M_WARN, "WARNING: cryptoapicert: ignoring certificate in store %s.",
827  validity < 0 ? "not yet valid" : "that has expired");
828  }
829 
830 out:
831  gc_free(&gc);
832  return rv;
833 }
834 
835 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
836 
837 static const CAPI_DATA *
838 retrieve_capi_data(EVP_PKEY *pkey)
839 {
840  const CAPI_DATA *cd = NULL;
841 
842  if (pkey && EVP_PKEY_id(pkey) == EVP_PKEY_RSA)
843  {
844  RSA *rsa = EVP_PKEY_get0_RSA(pkey);
845  if (rsa)
846  {
847  cd = (CAPI_DATA *)RSA_meth_get0_app_data(RSA_get_method(rsa));
848  }
849  }
850  return cd;
851 }
852 
853 static int
854 pkey_rsa_sign_init(EVP_PKEY_CTX *ctx)
855 {
856  msg(D_LOW, "cryptoapicert: enter pkey_rsa_sign_init");
857 
858  EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
859 
860  if (pkey && retrieve_capi_data(pkey))
861  {
862  return 1; /* Return success */
863  }
864  else if (default_pkey_sign_init) /* Not our key. Call the default method */
865  {
866  return default_pkey_sign_init(ctx);
867  }
868  return 1;
869 }
870 
877 static int
878 pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
879  const unsigned char *tbs, size_t tbslen)
880 {
881  EVP_PKEY *pkey = NULL;
882  const CAPI_DATA *cd = NULL;
883  EVP_MD *md = NULL;
884  const wchar_t *alg = NULL;
885 
886  int padding = 0;
887  int hashlen = 0;
888  int saltlen = 0;
889 
890  pkey = EVP_PKEY_CTX_get0_pkey(ctx);
891  if (pkey)
892  {
893  cd = retrieve_capi_data(pkey);
894  }
895 
896  /*
897  * We intercept all sign requests, not just the one's for our key.
898  * Check the key and call the saved OpenSSL method for unknown keys.
899  */
900  if (!pkey || !cd)
901  {
902  if (default_pkey_sign)
903  {
904  return default_pkey_sign(ctx, sig, siglen, tbs, tbslen);
905  }
906  else /* This should not happen */
907  {
908  msg(M_FATAL, "cryptopaicert: Unknown key and no default sign operation to fallback on");
909  return -1;
910  }
911  }
912 
913  if (!EVP_PKEY_CTX_get_rsa_padding(ctx, &padding))
914  {
915  padding = RSA_PKCS1_PADDING; /* Default padding for RSA */
916  }
917 
918  if (EVP_PKEY_CTX_get_signature_md(ctx, &md))
919  {
920  hashlen = EVP_MD_size(md);
921  alg = cng_hash_algo(EVP_MD_type(md));
922 
923  /*
924  * alg == NULL indicates legacy MD5+SHA1 hash, else alg should be a valid
925  * digest algorithm.
926  */
927  if (alg && wcscmp(alg, L"UNKNOWN") == 0)
928  {
929  RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_UNKNOWN_ALGORITHM_TYPE);
930  return -1;
931  }
932  }
933  else
934  {
935  msg(M_NONFATAL, "cryptoapicert: could not determine the signature digest algorithm");
936  RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_UNKNOWN_ALGORITHM_TYPE);
937  return -1;
938  }
939 
940  if (tbslen != (size_t)hashlen)
941  {
942  RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_INVALID_DIGEST_LENGTH);
943  return -1;
944  }
945 
946  /* If padding is PSS, determine parameters to pass to CNG */
947  if (padding == RSA_PKCS1_PSS_PADDING)
948  {
949  /*
950  * Ensure the digest type for signature and mask generation match.
951  * In CNG there is no option to specify separate hash functions for
952  * the two, but OpenSSL supports it. However, I have not seen the
953  * two being different in practice. Also the recommended practice is
954  * to use the same for both (rfc 8017 sec 8.1).
955  */
956  EVP_MD *mgf1md;
957  if (!EVP_PKEY_CTX_get_rsa_mgf1_md(ctx, &mgf1md)
958  || EVP_MD_type(mgf1md) != EVP_MD_type(md))
959  {
960  msg(M_NONFATAL, "cryptoapicert: Unknown MGF1 digest type or does"
961  " not match the signature digest type.");
962  RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_UNSUPPORTED_MASK_PARAMETER);
963  }
964 
965  if (!EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx, &saltlen))
966  {
967  msg(M_WARN, "cryptoapicert: unable to get the salt length from context."
968  " Using the default value.");
969  saltlen = -1;
970  }
971 
972  /*
973  * In OpenSSL saltlen = -1 indicates to use the size of the digest as
974  * size of the salt. A value of -2 or -3 indicates maximum salt length
975  * that will fit. See RSA_padding_add_PKCS1_PSS_mgf1() of OpenSSL.
976  */
977  if (saltlen == -1)
978  {
979  saltlen = hashlen;
980  }
981  else if (saltlen < 0)
982  {
983  const RSA *rsa = EVP_PKEY_get0_RSA(pkey);
984  saltlen = RSA_size(rsa) - hashlen - 2; /* max salt length for RSASSA-PSS */
985  if (RSA_bits(rsa) &0x7) /* number of bits in the key not a multiple of 8 */
986  {
987  saltlen--;
988  }
989  }
990 
991  if (saltlen < 0)
992  {
993  RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
994  return -1;
995  }
996  msg(D_LOW, "cryptoapicert: PSS padding using saltlen = %d", saltlen);
997  }
998 
999  msg(D_LOW, "cryptoapicert: calling priv_enc_CNG with alg = %ls", alg);
1000  *siglen = priv_enc_CNG(cd, alg, tbs, (int)tbslen, sig, *siglen,
1001  cng_padding_type(padding), (DWORD)saltlen);
1002 
1003  return (*siglen == 0) ? 0 : 1;
1004 }
1005 
1006 #endif /* OPENSSL_VERSION >= 1.1.0 */
1007 
1008 static int
1009 ssl_ctx_set_rsakey(SSL_CTX *ssl_ctx, CAPI_DATA *cd, EVP_PKEY *pkey)
1010 {
1011  RSA *rsa = NULL, *pub_rsa;
1012  RSA_METHOD *my_rsa_method = NULL;
1013  bool rsa_method_set = false;
1014 
1015  my_rsa_method = RSA_meth_new("Microsoft Cryptography API RSA Method",
1016  RSA_METHOD_FLAG_NO_CHECK);
1017  check_malloc_return(my_rsa_method);
1018  RSA_meth_set_pub_enc(my_rsa_method, rsa_pub_enc);
1019  RSA_meth_set_pub_dec(my_rsa_method, rsa_pub_dec);
1020  RSA_meth_set_priv_enc(my_rsa_method, rsa_priv_enc);
1021  RSA_meth_set_priv_dec(my_rsa_method, rsa_priv_dec);
1022  RSA_meth_set_init(my_rsa_method, NULL);
1023  RSA_meth_set_finish(my_rsa_method, finish);
1024  RSA_meth_set0_app_data(my_rsa_method, cd);
1025 
1026  /*
1027  * For CNG, set the RSA_sign method which gets priority over priv_enc().
1028  * This method is called with the raw hash without the digestinfo
1029  * header and works better when using NCryptSignHash() with some tokens.
1030  * However, if PSS padding is in use, openssl does not call this
1031  * function but adds the padding and then calls rsa_priv_enc()
1032  * with padding set to NONE which is not supported by CNG.
1033  * So, when posisble (OpenSSL 1.1.0 and up), we hook on to the sign
1034  * operation in EVP_PKEY_METHOD struct.
1035  */
1036  if (cd->key_spec == CERT_NCRYPT_KEY_SPEC)
1037  {
1038 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
1039  RSA_meth_set_sign(my_rsa_method, rsa_sign_CNG);
1040 #else
1041  /* pmethod is global -- initialize only if NULL */
1042  if (!pmethod)
1043  {
1044  pmethod = EVP_PKEY_meth_new(EVP_PKEY_RSA, 0);
1045  if (!pmethod)
1046  {
1047  SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_MALLOC_FAILURE);
1048  goto err;
1049  }
1050  const EVP_PKEY_METHOD *default_pmethod = EVP_PKEY_meth_find(EVP_PKEY_RSA);
1051  EVP_PKEY_meth_copy(pmethod, default_pmethod);
1052 
1053  /* We want to override only sign_init() and sign() */
1054  EVP_PKEY_meth_set_sign(pmethod, pkey_rsa_sign_init, pkey_rsa_sign);
1055  EVP_PKEY_meth_add0(pmethod);
1056 
1057  /* Keep a copy of the default sign and sign_init methods */
1058 
1059 #if (OPENSSL_VERSION_NUMBER < 0x1010009fL) /* > version 1.1.0i */
1060  /* The function signature is not const-correct in these versions */
1061  EVP_PKEY_meth_get_sign((EVP_PKEY_METHOD *)default_pmethod, &default_pkey_sign_init,
1063 #else
1064  EVP_PKEY_meth_get_sign(default_pmethod, &default_pkey_sign_init,
1066 
1067 #endif
1068  }
1069 #endif /* (OPENSSL_VERSION_NUMBER < 0x10100000L) */
1070  }
1071 
1072  rsa = RSA_new();
1073  if (rsa == NULL)
1074  {
1075  SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_MALLOC_FAILURE);
1076  goto err;
1077  }
1078 
1079  pub_rsa = EVP_PKEY_get0_RSA(pkey);
1080  if (!pub_rsa)
1081  {
1082  goto err;
1083  }
1084 
1085  /* Our private key is external, so we fill in only n and e from the public key */
1086  const BIGNUM *n = NULL;
1087  const BIGNUM *e = NULL;
1088  RSA_get0_key(pub_rsa, &n, &e, NULL);
1089  BIGNUM *rsa_n = BN_dup(n);
1090  BIGNUM *rsa_e = BN_dup(e);
1091  if (!rsa_n || !rsa_e || !RSA_set0_key(rsa, rsa_n, rsa_e, NULL))
1092  {
1093  BN_free(rsa_n); /* ok to free even if NULL */
1094  BN_free(rsa_e);
1095  msg(M_NONFATAL, "ERROR: %s: out of memory", __func__);
1096  goto err;
1097  }
1098  RSA_set_flags(rsa, RSA_flags(rsa) | RSA_FLAG_EXT_PKEY);
1099  if (!RSA_set_method(rsa, my_rsa_method))
1100  {
1101  goto err;
1102  }
1103  rsa_method_set = true; /* flag that method pointer will get freed with the key */
1104  cd->ref_count++; /* with method, cd gets assigned to the key as well */
1105 
1106  if (!SSL_CTX_use_RSAPrivateKey(ssl_ctx, rsa))
1107  {
1108  goto err;
1109  }
1110  /* SSL_CTX_use_RSAPrivateKey() increased the reference count in 'rsa', so
1111  * we decrease it here with RSA_free(), or it will never be cleaned up. */
1112  RSA_free(rsa);
1113  return 1;
1114 
1115 err:
1116  if (rsa)
1117  {
1118  RSA_free(rsa);
1119  }
1120  if (my_rsa_method && !rsa_method_set)
1121  {
1122  RSA_meth_free(my_rsa_method);
1123  }
1124  return 0;
1125 }
1126 
1127 int
1128 SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop)
1129 {
1130  HCERTSTORE cs;
1131  X509 *cert = NULL;
1132  CAPI_DATA *cd = calloc(1, sizeof(*cd));
1133 
1134  if (cd == NULL)
1135  {
1136  SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_MALLOC_FAILURE);
1137  goto err;
1138  }
1139  /* search CURRENT_USER first, then LOCAL_MACHINE */
1140  cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER
1142  if (cs == NULL)
1143  {
1145  goto err;
1146  }
1147  cd->cert_context = find_certificate_in_store(cert_prop, cs);
1148  CertCloseStore(cs, 0);
1149  if (!cd->cert_context)
1150  {
1151  cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE
1153  if (cs == NULL)
1154  {
1156  goto err;
1157  }
1158  cd->cert_context = find_certificate_in_store(cert_prop, cs);
1159  CertCloseStore(cs, 0);
1160  if (cd->cert_context == NULL)
1161  {
1163  goto err;
1164  }
1165  }
1166 
1167  /* cert_context->pbCertEncoded is the cert X509 DER encoded. */
1168  cert = d2i_X509(NULL, (const unsigned char **) &cd->cert_context->pbCertEncoded,
1169  cd->cert_context->cbCertEncoded);
1170  if (cert == NULL)
1171  {
1172  SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_ASN1_LIB);
1173  goto err;
1174  }
1175 
1176  /* set up stuff to use the private key */
1177  /* We prefer to get an NCRYPT key handle so that TLS1.2 can be supported */
1178  DWORD flags = CRYPT_ACQUIRE_COMPARE_KEY_FLAG
1179  | CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG;
1180  if (!CryptAcquireCertificatePrivateKey(cd->cert_context, flags, NULL,
1181  &cd->crypt_prov, &cd->key_spec, &cd->free_crypt_prov))
1182  {
1183  /* if we don't have a smart card reader here, and we try to access a
1184  * smart card certificate, we get:
1185  * "Error 1223: The operation was canceled by the user." */
1187  goto err;
1188  }
1189  /* here we don't need to do CryptGetUserKey() or anything; all necessary key
1190  * info is in cd->cert_context, and then, in cd->crypt_prov. */
1191 
1192  /* if we do not have an NCRYPT key handle restrict TLS to v1.1 or lower */
1193  int max_version = SSL_CTX_get_max_proto_version(ssl_ctx);
1194  if ((!max_version || max_version > TLS1_1_VERSION)
1195  && cd->key_spec != CERT_NCRYPT_KEY_SPEC)
1196  {
1197  msg(M_WARN, "WARNING: cryptoapicert: private key is in a legacy store."
1198  " Restricting TLS version to 1.1");
1199  if (SSL_CTX_get_min_proto_version(ssl_ctx) > TLS1_1_VERSION)
1200  {
1201  msg(M_NONFATAL,
1202  "ERROR: cryptoapicert: min TLS version larger than 1.1."
1203  " Try config option --tls-version-min 1.1");
1204  goto err;
1205  }
1206  if (!SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_1_VERSION))
1207  {
1208  msg(M_NONFATAL, "ERROR: cryptoapicert: set max TLS version failed");
1209  goto err;
1210  }
1211  }
1212 
1213  /* Public key in cert is NULL until we call SSL_CTX_use_certificate(),
1214  * so we do it here then... */
1215  if (!SSL_CTX_use_certificate(ssl_ctx, cert))
1216  {
1217  goto err;
1218  }
1219 
1220  /* the public key */
1221  EVP_PKEY *pkey = X509_get0_pubkey(cert);
1222 
1223  /* SSL_CTX_use_certificate() increased the reference count in 'cert', so
1224  * we decrease it here with X509_free(), or it will never be cleaned up. */
1225  X509_free(cert);
1226  cert = NULL;
1227 
1228  if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA)
1229  {
1230  if (!ssl_ctx_set_rsakey(ssl_ctx, cd, pkey))
1231  {
1232  goto err;
1233  }
1234  }
1235 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(OPENSSL_NO_EC)
1236  else if (EVP_PKEY_id(pkey) == EVP_PKEY_EC)
1237  {
1238  if (!ssl_ctx_set_eckey(ssl_ctx, cd, pkey))
1239  {
1240  goto err;
1241  }
1242  }
1243 #endif /* OPENSSL_VERSION_NUMBER >= 1.1.0 */
1244  else
1245  {
1246  msg(M_WARN, "WARNING: cryptoapicert: certificate type not supported");
1247  goto err;
1248  }
1249  CAPI_DATA_free(cd); /* this will do a ref_count-- */
1250  return 1;
1251 
1252 err:
1253  CAPI_DATA_free(cd);
1254  return 0;
1255 }
1256 
1257 #else /* ifdef ENABLE_CRYPTOAPI */
1258 #ifdef _MSC_VER /* Dummy function needed to avoid empty file compiler warning in Microsoft VC */
1259 static void
1260 dummy(void)
1261 {
1262 }
1263 #endif
1264 #endif /* _WIN32 */
#define M_NONFATAL
Definition: error.h:95
WCHAR * wide_string(const char *utf8, struct gc_arena *gc)
Definition: win32.c:1157
static int ssl_ctx_set_rsakey(SSL_CTX *ssl_ctx, CAPI_DATA *cd, EVP_PKEY *pkey)
Definition: cryptoapi.c:1009
#define CRYPTOAPI_F_CRYPT_ACQUIRE_CERTIFICATE_PRIVATE_KEY
Definition: cryptoapi.c:83
static ERR_STRING_DATA CRYPTOAPI_str_functs[]
Definition: cryptoapi.c:92
#define CRYPTOAPI_F_CRYPT_SET_HASH_PARAM
Definition: cryptoapi.c:86
static const CERT_CONTEXT * find_certificate_in_store(const char *cert_prop, HCERTSTORE cert_store)
Definition: cryptoapi.c:736
char * string_alloc(const char *str, struct gc_arena *gc)
Definition: buffer.c:685
#define CRYPTOAPI_F_CERT_FIND_CERTIFICATE_IN_STORE
Definition: cryptoapi.c:82
#define CRYPTOAPIerr(f)
Definition: cryptoapi.c:80
#define M_INFO
Definition: errlevel.h:55
struct _CAPI_DATA CAPI_DATA
BOOL free_crypt_prov
Definition: cryptoapi.c:120
#define CERT_STORE_READONLY_FLAG
Definition: cryptoapi.c:69
int ref_count
Definition: cryptoapi.c:121
static EVP_PKEY_METHOD * pmethod
Definition: cryptoapi.c:111
static void gc_free(struct gc_arena *a)
Definition: buffer.h:1023
static int rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
Definition: cryptoapi.c:383
static int RSA_meth_set_priv_dec(RSA_METHOD *meth, int(*priv_dec)(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding))
Set the private decoding function of an RSA_METHOD object.
static int rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
Definition: cryptoapi.c:508
static int priv_enc_CNG(const CAPI_DATA *cd, const wchar_t *hash_algo, const unsigned char *from, int flen, unsigned char *to, int tlen, DWORD padding, DWORD saltlen)
Sign the hash in &#39;from&#39; using NCryptSignHash().
Definition: cryptoapi.c:341
static int(* default_pkey_sign_init)(EVP_PKEY_CTX *ctx)
Definition: cryptoapi.c:112
static int RSA_meth_set0_app_data(RSA_METHOD *meth, void *app_data)
Set the application data of an RSA_METHOD object.
static int ec_data_idx
Definition: cryptoapi.c:108
static int RSA_meth_set_priv_enc(RSA_METHOD *meth, int(*priv_enc)(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding))
Set the private encoding function of an RSA_METHOD object.
static int RSA_meth_set_pub_dec(RSA_METHOD *meth, int(*pub_dec)(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding))
Set the public decoding function of an RSA_METHOD object.
#define CRYPTOAPI_F_CRYPT_SIGN_HASH
Definition: cryptoapi.c:87
static void dummy(void)
Definition: comp-lz4.c:320
static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey)
Get the EC_KEY object of a public key.
static void RSA_get0_key(const RSA *rsa, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
Get the RSA parameters.
static int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, long tls_ver_max)
Mimics SSL_CTX_set_max_proto_version for OpenSSL < 1.1.
#define ASSERT(x)
Definition: error.h:221
static int RSA_bits(const RSA *rsa)
Number of significant RSA bits.
#define ERR_MAP_SZ
int SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop)
Definition: cryptoapi.c:1128
static int rsa_pub_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
Definition: cryptoapi.c:310
#define D_LOW
Definition: errlevel.h:98
static void RSA_meth_free(RSA_METHOD *meth)
Free an existing RSA_METHOD object.
list flags
const CERT_CONTEXT * cert_context
Definition: cryptoapi.c:117
static EVP_PKEY * X509_get0_pubkey(const X509 *x)
Get the public key from a X509 certificate.
static struct gc_arena gc_new(void)
Definition: buffer.h:1015
#define malloc
Definition: cmocka.c:1795
static int RSA_meth_set_pub_enc(RSA_METHOD *meth, int(*pub_enc)(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding))
Set the public encoding function of an RSA_METHOD object.
#define CRYPTOAPI_F_CRYPT_GET_HASH_PARAM
Definition: cryptoapi.c:85
DWORD key_spec
Definition: cryptoapi.c:119
static RSA * EVP_PKEY_get0_RSA(EVP_PKEY *pkey)
Get the RSA object of a public key.
static RSA_METHOD * RSA_meth_new(const char *name, int flags)
Allocate a new RSA method object.
static SERVICE_STATUS status
Definition: automatic.c:43
#define CERT_STORE_OPEN_EXISTING_FLAG
Definition: cryptoapi.c:72
static char * ms_error_text(DWORD ms_err)
Definition: cryptoapi.c:222
#define msg
Definition: error.h:173
static int rsa_pub_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
Definition: cryptoapi.c:320
static void err_put_ms_error(DWORD ms_err, int func, const char *file, int line)
Definition: cryptoapi.c:259
#define ERR_LIB_CRYPTOAPI
Definition: cryptoapi.c:79
#define SSL_SIG_LENGTH
Definition: cryptoapi.c:76
static int init(RSA *rsa)
Definition: cryptoapi.c:518
static void check_malloc_return(const void *p)
Definition: buffer.h:1093
static int RSA_meth_set_sign(RSA_METHOD *meth, int(*sign)(int type, const unsigned char *m, unsigned int m_length, unsigned char *sigret, unsigned int *siglen, const RSA *rsa))
Set the sign function of an RSA_METHOD object.
static int rsa_sign_CNG(int type, const unsigned char *m, unsigned int m_len, unsigned char *sig, unsigned int *siglen, const RSA *rsa)
Sign the hash in |m| and return the signature in |sig|.
Definition: cryptoapi.c:479
#define M_FATAL
Definition: error.h:94
static int SSL_CTX_get_max_proto_version(SSL_CTX *ctx)
Return the max SSL protocol version currently enabled in the context.
#define CRYPTOAPI_F_GET_PROC_ADDRESS
Definition: cryptoapi.c:89
static int SSL_CTX_get_min_proto_version(SSL_CTX *ctx)
Return the min SSL protocol version currently enabled in the context.
static int finish(RSA *rsa)
Definition: cryptoapi.c:526
static DWORD cng_padding_type(int padding)
Definition: cryptoapi.c:128
#define CRYPTOAPI_F_LOAD_LIBRARY
Definition: cryptoapi.c:88
#define M_WARN
Definition: error.h:96
static const wchar_t * cng_hash_algo(int md_type)
Definition: cryptoapi.c:159
#define free
Definition: cmocka.c:1850
static void * RSA_meth_get0_app_data(const RSA_METHOD *meth)
Get the application data of an RSA_METHOD object.
static int RSA_set0_key(RSA *rsa, BIGNUM *n, BIGNUM *e, BIGNUM *d)
Set the RSA parameters.
Garbage collection arena used to keep track of dynamically allocated memory.
Definition: buffer.h:116
#define CRYPTOAPI_F_NCRYPT_SIGN_HASH
Definition: cryptoapi.c:90
static void CAPI_DATA_free(CAPI_DATA *cd)
Definition: cryptoapi.c:197
static int RSA_meth_set_init(RSA_METHOD *meth, int(*init)(RSA *rsa))
Set the init function of an RSA_METHOD object.
#define CRYPTOAPI_F_CRYPT_CREATE_HASH
Definition: cryptoapi.c:84
#define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT
#define CERT_SYSTEM_STORE_CURRENT_USER
Definition: cryptoapi.c:66
Definition: list.h:58
#define CRYPTOAPI_F_CERT_OPEN_SYSTEM_STORE
Definition: cryptoapi.c:81
HCRYPTPROV_OR_NCRYPT_KEY_HANDLE crypt_prov
Definition: cryptoapi.c:118
static void RSA_set_flags(RSA *rsa, int flags)
Set the RSA flags.
static int(* default_pkey_sign)(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen)
Definition: cryptoapi.c:113
static int RSA_meth_set_finish(RSA_METHOD *meth, int(*finish)(RSA *rsa))
Set the finish function of an RSA_METHOD object.