Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/manager/ssl/CSTrustDomain.cpp
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=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
#include "CSTrustDomain.h"
8
#include "mozilla/Base64.h"
9
#include "mozilla/Preferences.h"
10
#include "nsNSSCertificate.h"
11
#include "nsNSSComponent.h"
12
#include "nsServiceManagerUtils.h"
13
#include "nsThreadUtils.h"
14
#include "pkix/pkixnss.h"
15
16
using namespace mozilla::pkix;
17
18
namespace mozilla { namespace psm {
19
20
static LazyLogModule gTrustDomainPRLog("CSTrustDomain");
21
0
#define CSTrust_LOG(args) MOZ_LOG(gTrustDomainPRLog, LogLevel::Debug, args)
22
23
CSTrustDomain::CSTrustDomain(UniqueCERTCertList& certChain)
24
  : mCertChain(certChain)
25
  , mCertBlocklist(do_GetService(NS_CERTBLOCKLIST_CONTRACTID))
26
0
{
27
0
}
28
29
Result
30
CSTrustDomain::GetCertTrust(EndEntityOrCA endEntityOrCA,
31
                            const CertPolicyId& policy, Input candidateCertDER,
32
                            /*out*/ TrustLevel& trustLevel)
33
0
{
34
0
  MOZ_ASSERT(policy.IsAnyPolicy());
35
0
  if (!policy.IsAnyPolicy()) {
36
0
    return Result::FATAL_ERROR_INVALID_ARGS;
37
0
  }
38
0
39
0
  SECItem candidateCertDERSECItem = UnsafeMapInputToSECItem(candidateCertDER);
40
0
  UniqueCERTCertificate candidateCert(
41
0
    CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &candidateCertDERSECItem,
42
0
                            nullptr, false, true));
43
0
  if (!candidateCert) {
44
0
    return MapPRErrorCodeToResult(PR_GetError());
45
0
  }
46
0
47
0
  bool isCertRevoked;
48
0
  nsresult nsrv = mCertBlocklist->IsCertRevoked(
49
0
                    candidateCert->derIssuer.data,
50
0
                    candidateCert->derIssuer.len,
51
0
                    candidateCert->serialNumber.data,
52
0
                    candidateCert->serialNumber.len,
53
0
                    candidateCert->derSubject.data,
54
0
                    candidateCert->derSubject.len,
55
0
                    candidateCert->derPublicKey.data,
56
0
                    candidateCert->derPublicKey.len,
57
0
                    &isCertRevoked);
58
0
  if (NS_FAILED(nsrv)) {
59
0
    return Result::FATAL_ERROR_LIBRARY_FAILURE;
60
0
  }
61
0
62
0
  if (isCertRevoked) {
63
0
    CSTrust_LOG(("CSTrustDomain: certificate is revoked\n"));
64
0
    return Result::ERROR_REVOKED_CERTIFICATE;
65
0
  }
66
0
67
0
  // Is this cert our built-in content signing root?
68
0
  bool isRoot = false;
69
0
  nsCOMPtr<nsINSSComponent> component(do_GetService(PSM_COMPONENT_CONTRACTID));
70
0
  if (!component) {
71
0
    return Result::FATAL_ERROR_LIBRARY_FAILURE;
72
0
  }
73
0
  nsrv = component->IsCertContentSigningRoot(candidateCert.get(), &isRoot);
74
0
  if (NS_FAILED(nsrv)) {
75
0
    return Result::FATAL_ERROR_LIBRARY_FAILURE;
76
0
  }
77
0
  if (isRoot) {
78
0
    CSTrust_LOG(("CSTrustDomain: certificate is a trust anchor\n"));
79
0
    trustLevel = TrustLevel::TrustAnchor;
80
0
    return Success;
81
0
  }
82
0
  CSTrust_LOG(("CSTrustDomain: certificate is *not* a trust anchor\n"));
83
0
84
0
  trustLevel = TrustLevel::InheritsTrust;
85
0
  return Success;
86
0
}
87
88
Result
89
CSTrustDomain::FindIssuer(Input encodedIssuerName, IssuerChecker& checker,
90
                          Time time)
91
0
{
92
0
  // Loop over the chain, look for a matching subject
93
0
  for (CERTCertListNode* n = CERT_LIST_HEAD(mCertChain);
94
0
      !CERT_LIST_END(n, mCertChain); n = CERT_LIST_NEXT(n)) {
95
0
    Input certDER;
96
0
    Result rv = certDER.Init(n->cert->derCert.data, n->cert->derCert.len);
97
0
    if (rv != Success) {
98
0
      continue; // probably too big
99
0
    }
100
0
101
0
    // if the subject does not match, try the next certificate
102
0
    Input subjectDER;
103
0
    rv = subjectDER.Init(n->cert->derSubject.data, n->cert->derSubject.len);
104
0
    if (rv != Success) {
105
0
      continue; // just try the next one
106
0
    }
107
0
    if (!InputsAreEqual(subjectDER, encodedIssuerName)) {
108
0
      CSTrust_LOG(("CSTrustDomain: subjects don't match\n"));
109
0
      continue;
110
0
    }
111
0
112
0
    // If the subject does match, try the next step
113
0
    bool keepGoing;
114
0
    rv = checker.Check(certDER, nullptr/*additionalNameConstraints*/,
115
0
                       keepGoing);
116
0
    if (rv != Success) {
117
0
      return rv;
118
0
    }
119
0
    if (!keepGoing) {
120
0
      CSTrust_LOG(("CSTrustDomain: don't keep going\n"));
121
0
      break;
122
0
    }
123
0
  }
124
0
125
0
  return Success;
126
0
}
127
128
Result
129
CSTrustDomain::CheckRevocation(EndEntityOrCA endEntityOrCA,
130
                               const CertID& certID, Time time,
131
                               Duration validityDuration,
132
                               /*optional*/ const Input* stapledOCSPresponse,
133
                               /*optional*/ const Input* aiaExtension)
134
0
{
135
0
  // We're relying solely on the CertBlocklist for revocation - and we're
136
0
  // performing checks on this in GetCertTrust (as per nsNSSCertDBTrustDomain)
137
0
  return Success;
138
0
}
139
140
Result
141
CSTrustDomain::IsChainValid(const DERArray& certChain, Time time,
142
                            const CertPolicyId& requiredPolicy)
143
0
{
144
0
  MOZ_ASSERT(requiredPolicy.IsAnyPolicy());
145
0
  // Check that our chain is not empty
146
0
  if (certChain.GetLength() == 0) {
147
0
    return Result::FATAL_ERROR_LIBRARY_FAILURE;
148
0
  }
149
0
150
0
  return Success;
151
0
}
152
153
Result
154
CSTrustDomain::CheckSignatureDigestAlgorithm(DigestAlgorithm digestAlg,
155
                                             EndEntityOrCA endEntityOrCA,
156
                                             Time notBefore)
157
0
{
158
0
  if (digestAlg == DigestAlgorithm::sha1) {
159
0
    return Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED;
160
0
  }
161
0
  return Success;
162
0
}
163
164
Result
165
CSTrustDomain::CheckRSAPublicKeyModulusSizeInBits(
166
  EndEntityOrCA endEntityOrCA, unsigned int modulusSizeInBits)
167
0
{
168
0
  if (modulusSizeInBits < 2048) {
169
0
    return Result::ERROR_INADEQUATE_KEY_SIZE;
170
0
  }
171
0
  return Success;
172
0
}
173
174
Result
175
CSTrustDomain::VerifyRSAPKCS1SignedDigest(const SignedDigest& signedDigest,
176
                                          Input subjectPublicKeyInfo)
177
0
{
178
0
  return VerifyRSAPKCS1SignedDigestNSS(signedDigest, subjectPublicKeyInfo,
179
0
                                       nullptr);
180
0
}
181
182
Result
183
CSTrustDomain::CheckECDSACurveIsAcceptable(EndEntityOrCA endEntityOrCA,
184
                                           NamedCurve curve)
185
0
{
186
0
  switch (curve) {
187
0
    case NamedCurve::secp256r1: // fall through
188
0
    case NamedCurve::secp384r1: // fall through
189
0
    case NamedCurve::secp521r1:
190
0
      return Success;
191
0
  }
192
0
193
0
  return Result::ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
194
0
}
195
196
Result
197
CSTrustDomain::VerifyECDSASignedDigest(const SignedDigest& signedDigest,
198
                                       Input subjectPublicKeyInfo)
199
0
{
200
0
  return VerifyECDSASignedDigestNSS(signedDigest, subjectPublicKeyInfo,
201
0
                                    nullptr);
202
0
}
203
204
Result
205
CSTrustDomain::CheckValidityIsAcceptable(Time notBefore, Time notAfter,
206
                                         EndEntityOrCA endEntityOrCA,
207
                                         KeyPurposeId keyPurpose)
208
0
{
209
0
  return Success;
210
0
}
211
212
Result
213
CSTrustDomain::NetscapeStepUpMatchesServerAuth(Time notBefore,
214
                                               /*out*/ bool& matches)
215
0
{
216
0
  matches = false;
217
0
  return Success;
218
0
}
219
220
void
221
CSTrustDomain::NoteAuxiliaryExtension(AuxiliaryExtension /*extension*/,
222
                                      Input /*extensionData*/)
223
0
{
224
0
}
225
226
Result
227
CSTrustDomain::DigestBuf(Input item, DigestAlgorithm digestAlg,
228
                         /*out*/ uint8_t* digestBuf, size_t digestBufLen)
229
0
{
230
0
  return DigestBufNSS(item, digestAlg, digestBuf, digestBufLen);
231
0
}
232
233
} } // end namespace mozilla::psm