diff options
author | Ryan Sleevi <rsleevi@chromium.org> | 2020-01-11 01:30:44 +0000 |
---|---|---|
committer | Michal Klocek <michal.klocek@qt.io> | 2020-01-24 17:54:31 +0000 |
commit | f4f2d564d9448386e94d1e38d5133a2e73e8eb84 (patch) | |
tree | c1adb73aa8db2b682a04c67a6177f82fb07d47c7 | |
parent | a3c60650eae7a568e1e32b62ba3f7f51946f2ebd (diff) | |
download | qtwebengine-chromium-f4f2d564d9448386e94d1e38d5133a2e73e8eb84.tar.gz |
[Backport] CVE-2020-0601
Double-check signatures on verified chains
CryptoAPI allows third-parties to override a variety of functions,
potentially returning invalid chains. Add an extra signature check
to make sure the chain is reasonably sensible. This isn't perfect,
but is enough of a safety check until we switch to our verifier or
tighten down the blocking of 3P modules, even for CAPI.
Bug: 1040772
Change-Id: I7124da1f0399ba65e27bc1dd68c3b7499f5e99ec
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
-rw-r--r-- | chromium/net/cert/cert_verify_proc_win.cc | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/chromium/net/cert/cert_verify_proc_win.cc b/chromium/net/cert/cert_verify_proc_win.cc index 65f41ca1921..2cc23360af9 100644 --- a/chromium/net/cert/cert_verify_proc_win.cc +++ b/chromium/net/cert/cert_verify_proc_win.cc @@ -272,8 +272,10 @@ bool CertSubjectCommonNameHasNull(PCCERT_CONTEXT cert) { // calling this function. void GetCertChainInfo(PCCERT_CHAIN_CONTEXT chain_context, CertVerifyResult* verify_result) { - if (chain_context->cChain == 0) + if (chain_context->cChain == 0 || chain_context->rgpChain[0]->cElement == 0) { + verify_result->cert_status |= CERT_STATUS_INVALID; return; + } PCERT_SIMPLE_CHAIN first_chain = chain_context->rgpChain[0]; DWORD num_elements = first_chain->cElement; @@ -282,6 +284,26 @@ void GetCertChainInfo(PCCERT_CHAIN_CONTEXT chain_context, PCCERT_CONTEXT verified_cert = NULL; std::vector<PCCERT_CONTEXT> verified_chain; + // Recheck signatures in the event junk data was provided. + for (DWORD i = 0; i < num_elements - 1; ++i) { + PCCERT_CONTEXT issuer = element[i + 1]->pCertContext; + + // If Issuer isn't ECC, skip this certificate. + if (strcmp(issuer->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, + szOID_ECC_PUBLIC_KEY)) { + continue; + } + + PCCERT_CONTEXT cert = element[i]->pCertContext; + if (!CryptVerifyCertificateSignatureEx( + NULL, X509_ASN_ENCODING, CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT, + const_cast<PCERT_CONTEXT>(cert), CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT, + const_cast<PCERT_CONTEXT>(issuer), 0, NULL)) { + verify_result->cert_status |= CERT_STATUS_INVALID; + break; + } + } + bool has_root_ca = num_elements > 1 && !(chain_context->TrustStatus.dwErrorStatus & CERT_TRUST_IS_PARTIAL_CHAIN); |