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/. */
7 #ifndef TrustOverrides_h
8 #define TrustOverrides_h
10 #include "mozilla/ArrayUtils.h"
11 #include "mozpkix/pkix.h"
12 #include "mozpkix/pkixnss.h"
13 #include "mozpkix/pkixutil.h"
15 using namespace mozilla
;
16 using namespace mozilla::pkix
;
18 struct DataAndLength
{
24 static bool CertDNIsInList(const nsTArray
<uint8_t>& aCert
,
25 const DataAndLength (&aDnList
)[T
]) {
27 mozilla::pkix::Result rv
= certInput
.Init(aCert
.Elements(), aCert
.Length());
32 // we don't use the certificate for path building, so this parameter doesn't
34 EndEntityOrCA notUsedForPaths
= EndEntityOrCA::MustBeEndEntity
;
35 BackCert
cert(certInput
, notUsedForPaths
, nullptr);
41 Input
subject(cert
.GetSubject());
43 for (auto& dn
: aDnList
) {
45 rv
= dnInput
.Init(dn
.data
, dn
.len
);
50 if (InputsAreEqual(subject
, dnInput
)) {
58 static bool CertSPKIIsInList(Input aCertInput
,
59 const DataAndLength (&aSpkiList
)[T
]) {
60 // we don't use the certificate for path building, so this parameter doesn't
62 EndEntityOrCA notUsedForPaths
= EndEntityOrCA::MustBeEndEntity
;
63 BackCert
cert(aCertInput
, notUsedForPaths
, nullptr);
64 mozilla::pkix::Result rv
= cert
.Init();
69 Input
publicKey(cert
.GetSubjectPublicKeyInfo());
71 for (auto& spki
: aSpkiList
) {
73 rv
= spkiInput
.Init(spki
.data
, spki
.len
);
78 if (InputsAreEqual(publicKey
, spkiInput
)) {
85 template <size_t T
, size_t R
>
86 static bool CertMatchesStaticData(const nsTArray
<uint8_t>& aCert
,
87 const unsigned char (&subject
)[T
],
88 const unsigned char (&spki
)[R
]) {
90 mozilla::pkix::Result rv
= certInput
.Init(aCert
.Elements(), aCert
.Length());
95 // we don't use the certificate for path building, so this parameter doesn't
97 EndEntityOrCA notUsedForPaths
= EndEntityOrCA::MustBeEndEntity
;
98 BackCert
cert(certInput
, notUsedForPaths
, nullptr);
104 Input
certSubject(cert
.GetSubject());
105 Input
certSPKI(cert
.GetSubjectPublicKeyInfo());
108 rv
= subjectInput
.Init(subject
, T
);
114 rv
= spkiInput
.Init(spki
, R
);
119 return InputsAreEqual(certSubject
, subjectInput
) &&
120 InputsAreEqual(certSPKI
, spkiInput
);
123 // Implements the graduated Symantec distrust algorithm from Bug 1409257.
124 // This accepts a pre-segmented certificate chain (e.g. SegmentCertificateChain)
125 // as |intCerts|, and pre-assumes that the root has been identified
126 // as being affected (this is to avoid duplicate Segment operations in the
127 // NSSCertDBTrustDomain). Each of the |intCerts| is evaluated against a
128 // |allowlist| of SPKI entries, and if a match is found, then this returns
129 // "not distrusted." Otherwise, due to the precondition holding, the chain is
132 static nsresult
CheckForSymantecDistrust(const nsTArray
<Input
>& intCerts
,
133 const DataAndLength (&allowlist
)[T
],
134 /* out */ bool& isDistrusted
) {
135 // PRECONDITION: The rootCert is already verified as being one of the
136 // affected Symantec roots
140 for (const auto& cert
: intCerts
) {
141 if (CertSPKIIsInList(cert
, allowlist
)) {
142 isDistrusted
= false;
149 #endif // TrustOverrides_h