summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Sleevi <rsleevi@chromium.org>2020-01-11 01:30:44 +0000
committerMichal Klocek <michal.klocek@qt.io>2020-01-24 17:54:31 +0000
commitf4f2d564d9448386e94d1e38d5133a2e73e8eb84 (patch)
treec1adb73aa8db2b682a04c67a6177f82fb07d47c7
parenta3c60650eae7a568e1e32b62ba3f7f51946f2ebd (diff)
downloadqtwebengine-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.cc24
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);