CSTrustDomain.cpp 7.1 KB

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