Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/certverifier/TrustOverrideUtils.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef TrustOverrides_h
8
#define TrustOverrides_h
9
10
#include "nsNSSCertificate.h"
11
#include "nsNSSCertValidity.h"
12
#include "mozilla/ArrayUtils.h"
13
14
using namespace mozilla;
15
16
struct DataAndLength {
17
  const uint8_t* data;
18
  uint32_t len;
19
};
20
21
template<size_t T>
22
static bool
23
CertDNIsInList(const CERTCertificate* aCert, const DataAndLength (&aDnList)[T])
24
0
{
25
0
  MOZ_ASSERT(aCert);
26
0
  if (!aCert) {
27
0
    return false;
28
0
  }
29
0
30
0
  for (auto& dn: aDnList) {
31
0
    if (aCert->derSubject.len == dn.len &&
32
0
        mozilla::ArrayEqual(aCert->derSubject.data, dn.data, dn.len)) {
33
0
      return true;
34
0
    }
35
0
  }
36
0
  return false;
37
0
}
Unexecuted instantiation: Unified_cpp_certverifier0.cpp:bool CertDNIsInList<6ul>(CERTCertificateStr const*, DataAndLength const (&) [6ul])
Unexecuted instantiation: Unified_cpp_certverifier0.cpp:bool CertDNIsInList<19ul>(CERTCertificateStr const*, DataAndLength const (&) [19ul])
Unexecuted instantiation: Unified_cpp_security_manager_ssl1.cpp:bool CertDNIsInList<1ul>(CERTCertificateStr const*, DataAndLength const (&) [1ul])
Unexecuted instantiation: Unified_cpp_security_manager_ssl1.cpp:bool CertDNIsInList<19ul>(CERTCertificateStr const*, DataAndLength const (&) [19ul])
Unexecuted instantiation: TrustOverrideTest.cpp:bool CertDNIsInList<1ul>(CERTCertificateStr const*, DataAndLength const (&) [1ul])
38
39
template<size_t T>
40
static bool
41
CertSPKIIsInList(const CERTCertificate* aCert, const DataAndLength (&aSpkiList)[T])
42
0
{
43
0
  MOZ_ASSERT(aCert);
44
0
  if (!aCert) {
45
0
    return false;
46
0
  }
47
0
48
0
  for (auto& spki: aSpkiList) {
49
0
    if (aCert->derPublicKey.len == spki.len &&
50
0
        mozilla::ArrayEqual(aCert->derPublicKey.data, spki.data, spki.len)) {
51
0
      return true;
52
0
    }
53
0
  }
54
0
  return false;
55
0
}
Unexecuted instantiation: Unified_cpp_certverifier0.cpp:bool CertSPKIIsInList<12ul>(CERTCertificateStr const*, DataAndLength const (&) [12ul])
Unexecuted instantiation: Unified_cpp_security_manager_ssl1.cpp:bool CertSPKIIsInList<12ul>(CERTCertificateStr const*, DataAndLength const (&) [12ul])
Unexecuted instantiation: TrustOverrideTest.cpp:bool CertSPKIIsInList<1ul>(CERTCertificateStr const*, DataAndLength const (&) [1ul])
56
57
template<size_t T, size_t R>
58
static bool
59
CertMatchesStaticData(const CERTCertificate* cert,
60
                      const unsigned char (&subject)[T],
61
0
                      const unsigned char (&spki)[R]) {
62
0
  MOZ_ASSERT(cert);
63
0
  if (!cert) {
64
0
    return false;
65
0
  }
66
0
  return cert->derSubject.len == T &&
67
0
         mozilla::ArrayEqual(cert->derSubject.data, subject, T) &&
68
0
         cert->derPublicKey.len == R &&
69
0
         mozilla::ArrayEqual(cert->derPublicKey.data, spki, R);
70
0
}
Unexecuted instantiation: Unified_cpp_certverifier0.cpp:bool CertMatchesStaticData<78ul, 294ul>(CERTCertificateStr const*, unsigned char const (&) [78ul], unsigned char const (&) [294ul])
Unexecuted instantiation: Unified_cpp_certverifier0.cpp:bool CertMatchesStaticData<100ul, 294ul>(CERTCertificateStr const*, unsigned char const (&) [100ul], unsigned char const (&) [294ul])
71
72
// Implements the graduated Symantec distrust algorithm from Bug 1409257.
73
// This accepts a pre-segmented certificate chain (e.g. SegmentCertificateChain)
74
// as |intCerts| and |eeCert|, and pre-assumes that the root has been identified
75
// as being affected (this is to avoid duplicate Segment operations in the
76
// NSSCertDBTrustDomain). If |permitAfterDate| is non-zero, this algorithm
77
// returns "not distrusted" if the NotBefore date of |eeCert| is after
78
// the |permitAfterDate|. Then each of the |intCerts| is evaluated against a
79
// |whitelist| of SPKI entries, and if a match is found, then this returns
80
// "not distrusted." Otherwise, due to the precondition holding, the chain is
81
// "distrusted."
82
template<size_t T>
83
static nsresult
84
CheckForSymantecDistrust(const nsCOMPtr<nsIX509CertList>& intCerts,
85
                         const nsCOMPtr<nsIX509Cert>& eeCert,
86
                         const PRTime& permitAfterDate,
87
                         const DataAndLength (&whitelist)[T],
88
                         /* out */ bool& isDistrusted)
89
0
{
90
0
    // PRECONDITION: The rootCert is already verified as being one of the
91
0
    // affected Symantec roots
92
0
93
0
    // Check the preference to see if this is enabled before proceeding.
94
0
    // TODO in Bug 1437754
95
0
96
0
    isDistrusted = true;
97
0
98
0
    // Only check the validity period if we're asked
99
0
    if (permitAfterDate > 0) {
100
0
      // We need to verify the age of the end entity
101
0
      nsCOMPtr<nsIX509CertValidity> validity;
102
0
      nsresult rv = eeCert->GetValidity(getter_AddRefs(validity));
103
0
      if (NS_FAILED(rv)) {
104
0
        return rv;
105
0
      }
106
0
107
0
      PRTime notBefore;
108
0
      rv = validity->GetNotBefore(&notBefore);
109
0
      if (NS_FAILED(rv)) {
110
0
        return rv;
111
0
      }
112
0
113
0
      // If the end entity's notBefore date is after the permitAfter date, this
114
0
      // algorithm doesn't apply, so exit false before we do any iterating.
115
0
      if (notBefore >= permitAfterDate) {
116
0
        isDistrusted = false;
117
0
        return NS_OK;
118
0
      }
119
0
    }
120
0
121
0
    // Look for one of the intermediates to be in the whitelist
122
0
    RefPtr<nsNSSCertList> intCertList = intCerts->GetCertList();
123
0
124
0
    return intCertList->ForEachCertificateInChain(
125
0
      [&isDistrusted, &whitelist] (nsCOMPtr<nsIX509Cert> aCert, bool aHasMore,
126
0
                                   /* out */ bool& aContinue) {
127
0
        // We need an owning handle when calling nsIX509Cert::GetCert().
128
0
        UniqueCERTCertificate nssCert(aCert->GetCert());
129
0
        if (CertSPKIIsInList(nssCert.get(), whitelist)) {
130
0
          // In the whitelist
131
0
          isDistrusted = false;
132
0
          aContinue = false;
133
0
        }
134
0
        return NS_OK;
135
0
    });
Unexecuted instantiation: Unified_cpp_certverifier0.cpp:nsresult CheckForSymantecDistrust<12ul>(nsCOMPtr<nsIX509CertList> const&, nsCOMPtr<nsIX509Cert> const&, long const&, DataAndLength const (&) [12ul], bool&)::{lambda(nsCOMPtr<nsIX509Cert>, bool, bool&)#1}::operator()(nsCOMPtr<nsIX509Cert>, bool, bool&) const
Unexecuted instantiation: Unified_cpp_security_manager_ssl1.cpp:nsresult CheckForSymantecDistrust<12ul>(nsCOMPtr<nsIX509CertList> const&, nsCOMPtr<nsIX509Cert> const&, long const&, DataAndLength const (&) [12ul], bool&)::{lambda(nsCOMPtr<nsIX509Cert>, bool, bool&)#1}::operator()(nsCOMPtr<nsIX509Cert>, bool, bool&) const
136
0
}
Unexecuted instantiation: Unified_cpp_certverifier0.cpp:nsresult CheckForSymantecDistrust<12ul>(nsCOMPtr<nsIX509CertList> const&, nsCOMPtr<nsIX509Cert> const&, long const&, DataAndLength const (&) [12ul], bool&)
Unexecuted instantiation: Unified_cpp_security_manager_ssl1.cpp:nsresult CheckForSymantecDistrust<12ul>(nsCOMPtr<nsIX509CertList> const&, nsCOMPtr<nsIX509Cert> const&, long const&, DataAndLength const (&) [12ul], bool&)
137
138
#endif // TrustOverrides_h