34 #elif defined(_MSC_VER)
40 #ifdef ENABLE_CRYPTOAPI
42 #include <openssl/ssl.h>
43 #include <openssl/evp.h>
44 #include <openssl/err.h>
57 #ifndef HAVE_XKEY_PROVIDER
65 size_t *siglen,
const unsigned char *tbs,
size_t tbslen);
67 static XKEY_EXTERNAL_SIGN_fn xkey_cng_sign;
84 static const wchar_t *
87 const wchar_t *alg = L
"UNKNOWN";
91 alg = BCRYPT_MD5_ALGORITHM;
95 alg = BCRYPT_SHA1_ALGORITHM;
99 alg = BCRYPT_SHA256_ALGORITHM;
103 alg = BCRYPT_SHA384_ALGORITHM;
107 alg = BCRYPT_SHA512_ALGORITHM;
116 msg(
M_WARN|
M_INFO,
"cryptoapicert: Unknown hash type NID=0x%x", md_type);
131 if (cd->
key_spec == CERT_NCRYPT_KEY_SPEC)
144 EVP_PKEY_free(cd->
pubkey);
149 #ifndef HAVE_XKEY_PROVIDER
164 case RSA_PKCS1_PADDING:
165 pad = BCRYPT_PAD_PKCS1;
168 case RSA_PKCS1_PSS_PADDING:
169 pad = BCRYPT_PAD_PSS;
194 int flen,
unsigned char *to,
int tlen, DWORD padding, DWORD saltlen)
202 msg(
D_LOW,
"Signing hash using CNG: data size = %d padding = %lu", flen, padding);
204 if (padding == BCRYPT_PAD_PKCS1)
206 BCRYPT_PKCS1_PADDING_INFO padinfo = {hash_algo};
207 status = NCryptSignHash(hkey, &padinfo, (BYTE *)from, flen,
208 to, tlen, &len, padding);
210 else if (padding == BCRYPT_PAD_PSS)
212 BCRYPT_PSS_PADDING_INFO padinfo = {hash_algo, saltlen};
213 status = NCryptSignHash(hkey, &padinfo, (BYTE *)from, flen,
214 to, tlen, &len, padding);
218 msg(
M_NONFATAL,
"Error in cryptoapicert: Unknown padding type");
222 if (
status != ERROR_SUCCESS)
237 const RSA_METHOD *rsa_meth = RSA_get_method(rsa);
279 ECDSA_SIG *ecsig = NULL;
281 BIGNUM *r = BN_bin2bn(buf, rlen, NULL);
282 BIGNUM *s = BN_bin2bn(buf+rlen, rlen, NULL);
287 ecsig = ECDSA_SIG_new();
292 if (!ECDSA_SIG_set0(ecsig, r, s))
294 ECDSA_SIG_free(ecsig);
304 #ifndef HAVE_XKEY_PROVIDER
309 const BIGNUM *in_kinv,
const BIGNUM *in_r, EC_KEY *ec)
311 ECDSA_SIG *ecsig = NULL;
318 DWORD len = _countof(buf);
320 msg(
D_LOW,
"Cryptoapi: signing hash using EC key: data size = %d", dgstlen);
322 DWORD
status = NCryptSignHash(hkey, NULL, (BYTE *)dgst, dgstlen, (BYTE *)buf, len, &len, 0);
323 if (
status != ERROR_SUCCESS)
338 ecdsa_sign(
int type,
const unsigned char *dgst,
int dgstlen,
unsigned char *sig,
339 unsigned int *siglen,
const BIGNUM *kinv,
const BIGNUM *r, EC_KEY *ec)
351 int len = i2d_ECDSA_SIG(s, NULL);
352 if (len > ECDSA_size(ec))
355 msg(
M_NONFATAL,
"Error in cryptoapicert: DER encoded ECDSA signature is too long (%d bytes)", len);
358 *siglen = i2d_ECDSA_SIG(s, &sig);
368 EVP_PKEY *privkey = NULL;
371 ec_method = EC_KEY_METHOD_new(EC_KEY_OpenSSL());
394 ec_data_idx = EC_KEY_get_ex_new_index(0,
"cryptapicert ec key", NULL, NULL, NULL);
405 privkey = EVP_PKEY_new();
406 if (!EVP_PKEY_assign_EC_KEY(privkey, ec))
413 if (!SSL_CTX_use_PrivateKey(ssl_ctx, privkey))
417 EVP_PKEY_free(privkey);
423 EVP_PKEY_free(privkey);
439 static const CERT_CONTEXT *
449 const CERT_CONTEXT *rv = NULL;
451 const void *find_param;
452 unsigned char hash[255];
453 CRYPT_HASH_BLOB blob = {.cbData = 0, .pbData =
hash};
456 if (!strncmp(cert_prop,
"SUBJ:", 5))
460 find_type = CERT_FIND_SUBJECT_STR_W;
462 else if (!strncmp(cert_prop,
"THUMB:", 6))
466 find_type = CERT_FIND_HASH;
471 for (p = cert_prop, i = 0; *p && i <
sizeof(
hash); i++)
473 if (*p >=
'0' && *p <=
'9')
477 else if (*p >=
'A' && *p <=
'F')
479 x = (*p -
'A' + 10) << 4;
481 else if (*p >=
'a' && *p <=
'f')
483 x = (*p -
'a' + 10) << 4;
487 msg(
M_WARN|
M_INFO,
"WARNING: cryptoapicert: error parsing <THUMB:%s>.", cert_prop);
490 if (*p >=
'0' && *p <=
'9')
494 else if (*p >=
'A' && *p <=
'F')
498 else if (*p >=
'a' && *p <=
'f')
504 for (p++; *p && *p ==
' '; p++)
512 msg(
M_NONFATAL,
"Error in cryptoapicert: unsupported certificate specification <%s>", cert_prop);
520 rv = CertFindCertificateInStore(cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
521 0, find_type, find_param, rv);
524 validity = CertVerifyTimeValidity(NULL, rv->pCertInfo);
526 if (!rv || validity == 0)
530 msg(
M_WARN|
M_INFO,
"WARNING: cryptoapicert: ignoring certificate in store %s.",
531 validity < 0 ?
"not yet valid" :
"that has expired");
539 #ifndef HAVE_XKEY_PROVIDER
546 if (pkey && EVP_PKEY_id(pkey) == EVP_PKEY_RSA)
560 msg(
D_LOW,
"cryptoapicert: enter pkey_rsa_sign_init");
562 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
583 const unsigned char *tbs,
size_t tbslen)
585 EVP_PKEY *pkey = NULL;
588 const wchar_t *alg = NULL;
594 pkey = EVP_PKEY_CTX_get0_pkey(ctx);
612 msg(
M_FATAL,
"Error in cryptoapicert: Unknown key and no default sign operation to fallback on");
617 if (!EVP_PKEY_CTX_get_rsa_padding(ctx, &padding))
619 padding = RSA_PKCS1_PADDING;
622 if (EVP_PKEY_CTX_get_signature_md(ctx, &md))
624 hashlen = EVP_MD_size(md);
631 if (alg && wcscmp(alg, L
"UNKNOWN") == 0)
633 msg(
M_NONFATAL,
"Error in cryptoapicert: Unknown hash algorithm <%d>", EVP_MD_type(md));
639 msg(
M_NONFATAL,
"Error in cryptoapicert: could not determine the signature digest algorithm");
643 if (tbslen != (
size_t)hashlen)
645 msg(
M_NONFATAL,
"Error in cryptoapicert: data size does not match hash");
650 if (padding == RSA_PKCS1_PSS_PADDING)
660 if (!EVP_PKEY_CTX_get_rsa_mgf1_md(ctx, &mgf1md)
661 || EVP_MD_type(mgf1md) != EVP_MD_type(md))
663 msg(
M_NONFATAL,
"Error in cryptoapicert: Unknown MGF1 digest type or does"
664 " not match the signature digest type.");
668 if (!EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx, &saltlen))
670 msg(
M_WARN|
M_INFO,
"cryptoapicert: unable to get the salt length from context."
671 " Using the default value.");
684 else if (saltlen < 0)
687 saltlen = RSA_size(rsa) - hashlen - 2;
696 msg(
M_NONFATAL,
"Error in cryptoapicert: invalid salt length (%d). Digest too large for keysize?", saltlen);
699 msg(
D_LOW,
"cryptoapicert: PSS padding using saltlen = %d", saltlen);
702 msg(
D_LOW,
"cryptoapicert: calling priv_enc_CNG with alg = %ls", alg);
703 *siglen =
priv_enc_CNG(cd, alg, tbs, (
int)tbslen, sig, (
int)*siglen,
706 return (*siglen == 0) ? 0 : 1;
713 RSA_METHOD *my_rsa_method = NULL;
714 EVP_PKEY *privkey = NULL;
717 my_rsa_method =
RSA_meth_new(
"Microsoft Cryptography API RSA Method",
718 RSA_METHOD_FLAG_NO_CHECK);
726 pmethod = EVP_PKEY_meth_new(EVP_PKEY_RSA, 0);
729 msg(
M_NONFATAL,
"Error in cryptoapicert: failed to create EVP_PKEY_METHOD");
732 const EVP_PKEY_METHOD *default_pmethod = EVP_PKEY_meth_find(EVP_PKEY_RSA);
733 EVP_PKEY_meth_copy(
pmethod, default_pmethod);
745 rsa = EVP_PKEY_get1_RSA(pkey);
748 if (!RSA_set_method(rsa, my_rsa_method))
752 my_rsa_method = NULL;
755 privkey = EVP_PKEY_new();
756 if (!EVP_PKEY_assign_RSA(privkey, rsa))
762 if (!SSL_CTX_use_PrivateKey(ssl_ctx, privkey))
779 EVP_PKEY_free(privkey);
789 xkey_cng_ec_sign(
CAPI_DATA *cd,
unsigned char *sig,
size_t *siglen,
const unsigned char *tbs,
793 DWORD len = _countof(buf);
795 msg(
D_LOW,
"Signing using NCryptSignHash with EC key");
797 DWORD
status = NCryptSignHash(cd->
crypt_prov, NULL, (BYTE *)tbs, tbslen, buf, len, &len, 0);
799 if (
status != ERROR_SUCCESS)
810 msg(
M_NONFATAL,
"Error in cryptopicert: Failed to convert ECDSA signature");
815 if (i2d_ECDSA_SIG(ecsig, NULL) > EVP_PKEY_size(cd->
pubkey))
817 ECDSA_SIG_free(ecsig);
818 msg(
M_NONFATAL,
"Error in cryptoapicert: DER encoded ECDSA signature is too long");
822 *siglen = i2d_ECDSA_SIG(ecsig, &sig);
823 ECDSA_SIG_free(ecsig);
825 return (*siglen > 0);
830 xkey_cng_rsa_sign(
CAPI_DATA *cd,
unsigned char *sig,
size_t *siglen,
const unsigned char *tbs,
831 size_t tbslen, XKEY_SIGALG sigalg)
839 DWORD
status = ERROR_SUCCESS;
842 const wchar_t *hashalg =
cng_hash_algo(OBJ_sn2nid(sigalg.mdname));
844 if (hashalg && wcscmp(hashalg, L
"UNKNOWN") == 0)
846 msg(
M_NONFATAL,
"Error in cryptoapicert: Unknown hash name <%s>", sigalg.mdname);
850 if (!strcmp(sigalg.padmode,
"pkcs1"))
852 msg(
D_LOW,
"Signing using NCryptSignHash with PKCS1 padding: hashalg <%s>", sigalg.mdname);
854 BCRYPT_PKCS1_PADDING_INFO padinfo = {hashalg};
855 status = NCryptSignHash(cd->
crypt_prov, &padinfo, (BYTE *)tbs, (DWORD)tbslen,
856 sig, (DWORD)*siglen, &len, BCRYPT_PAD_PKCS1);
858 else if (!strcmp(sigalg.padmode,
"pss"))
860 int saltlen = tbslen;
861 if (!strcmp(sigalg.saltlen,
"max"))
863 saltlen = xkey_max_saltlen(EVP_PKEY_bits(cd->
pubkey), tbslen);
866 msg(
M_NONFATAL,
"Error in cryptoapicert: invalid salt length (%d)", saltlen);
871 msg(
D_LOW,
"Signing using NCryptSignHash with PSS padding: hashalg <%s>, saltlen <%d>",
872 sigalg.mdname, saltlen);
874 BCRYPT_PSS_PADDING_INFO padinfo = {hashalg, (DWORD) saltlen};
875 status = NCryptSignHash(cd->
crypt_prov, &padinfo, (BYTE *)tbs, (DWORD) tbslen,
876 sig, (DWORD)*siglen, &len, BCRYPT_PAD_PSS);
880 msg(
M_NONFATAL,
"Error in cryptoapicert: Unsupported padding mode <%s>", sigalg.padmode);
884 if (
status != ERROR_SUCCESS)
892 return (*siglen > 0);
897 xkey_cng_sign(
void *handle,
unsigned char *sig,
size_t *siglen,
const unsigned char *tbs,
898 size_t tbslen, XKEY_SIGALG sigalg)
907 unsigned char mdbuf[EVP_MAX_MD_SIZE];
908 size_t buflen = _countof(mdbuf);
911 if (!strcmp(sigalg.op,
"DigestSign"))
913 if (!xkey_digest(tbs, tbslen, mdbuf, &buflen, sigalg.mdname))
921 if (!strcmp(sigalg.keytype,
"EC"))
923 return xkey_cng_ec_sign(cd, sig, siglen, tbs, tbslen);
925 else if (!strcmp(sigalg.keytype,
"RSA"))
927 return xkey_cng_rsa_sign(cd, sig, siglen, tbs, tbslen, sigalg);
950 cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER
951 |CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, L
"MY");
958 CertCloseStore(cs, 0);
961 cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE
962 |CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, L
"MY");
969 CertCloseStore(cs, 0);
972 msg(
M_NONFATAL,
"Error in cryptoapicert: certificate matching <%s> not found", cert_prop);
978 cert = d2i_X509(NULL, (
const unsigned char **) &cd->
cert_context->pbCertEncoded,
982 msg(
M_NONFATAL,
"Error in cryptoapicert: X509 certificate decode failed");
988 DWORD flags = CRYPT_ACQUIRE_COMPARE_KEY_FLAG
989 | CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG;
990 if (!CryptAcquireCertificatePrivateKey(cd->
cert_context, flags, NULL,
995 "is in a legacy token not supported by Windows CNG API");
1001 if (!SSL_CTX_use_certificate(ssl_ctx, cert))
1007 EVP_PKEY *pkey = X509_get_pubkey(cert);
1015 #ifdef HAVE_XKEY_PROVIDER
1017 EVP_PKEY *privkey = xkey_load_generic_key(
tls_libctx, cd, pkey,
1019 SSL_CTX_use_PrivateKey(ssl_ctx, privkey);
1024 if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA)
1031 else if (EVP_PKEY_id(pkey) == EVP_PKEY_EC)
1040 msg(
M_WARN|
M_INFO,
"WARNING: cryptoapicert: key type <%d> not supported",