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