security/apps/AppTrustDomain.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifdef MOZ_LOGGING
michael@0 8 #define FORCE_PR_LOG 1
michael@0 9 #endif
michael@0 10
michael@0 11 #include "AppTrustDomain.h"
michael@0 12 #include "certdb.h"
michael@0 13 #include "pkix/pkix.h"
michael@0 14 #include "mozilla/ArrayUtils.h"
michael@0 15 #include "nsIX509CertDB.h"
michael@0 16 #include "prerror.h"
michael@0 17 #include "secerr.h"
michael@0 18
michael@0 19 // Generated in Makefile.in
michael@0 20 #include "marketplace-prod-public.inc"
michael@0 21 #include "marketplace-prod-reviewers.inc"
michael@0 22 #include "marketplace-dev-public.inc"
michael@0 23 #include "marketplace-dev-reviewers.inc"
michael@0 24 #include "xpcshell.inc"
michael@0 25
michael@0 26 using namespace mozilla::pkix;
michael@0 27
michael@0 28 #ifdef PR_LOGGING
michael@0 29 extern PRLogModuleInfo* gPIPNSSLog;
michael@0 30 #endif
michael@0 31
michael@0 32 namespace mozilla { namespace psm {
michael@0 33
michael@0 34 AppTrustDomain::AppTrustDomain(void* pinArg)
michael@0 35 : mPinArg(pinArg)
michael@0 36 {
michael@0 37 }
michael@0 38
michael@0 39 SECStatus
michael@0 40 AppTrustDomain::SetTrustedRoot(AppTrustedRoot trustedRoot)
michael@0 41 {
michael@0 42 SECItem trustedDER;
michael@0 43
michael@0 44 // Load the trusted certificate into the in-memory NSS database so that
michael@0 45 // CERT_CreateSubjectCertList can find it.
michael@0 46
michael@0 47 switch (trustedRoot)
michael@0 48 {
michael@0 49 case nsIX509CertDB::AppMarketplaceProdPublicRoot:
michael@0 50 trustedDER.data = const_cast<uint8_t*>(marketplaceProdPublicRoot);
michael@0 51 trustedDER.len = mozilla::ArrayLength(marketplaceProdPublicRoot);
michael@0 52 break;
michael@0 53
michael@0 54 case nsIX509CertDB::AppMarketplaceProdReviewersRoot:
michael@0 55 trustedDER.data = const_cast<uint8_t*>(marketplaceProdReviewersRoot);
michael@0 56 trustedDER.len = mozilla::ArrayLength(marketplaceProdReviewersRoot);
michael@0 57 break;
michael@0 58
michael@0 59 case nsIX509CertDB::AppMarketplaceDevPublicRoot:
michael@0 60 trustedDER.data = const_cast<uint8_t*>(marketplaceDevPublicRoot);
michael@0 61 trustedDER.len = mozilla::ArrayLength(marketplaceDevPublicRoot);
michael@0 62 break;
michael@0 63
michael@0 64 case nsIX509CertDB::AppMarketplaceDevReviewersRoot:
michael@0 65 trustedDER.data = const_cast<uint8_t*>(marketplaceDevReviewersRoot);
michael@0 66 trustedDER.len = mozilla::ArrayLength(marketplaceDevReviewersRoot);
michael@0 67 break;
michael@0 68
michael@0 69 case nsIX509CertDB::AppXPCShellRoot:
michael@0 70 trustedDER.data = const_cast<uint8_t*>(xpcshellRoot);
michael@0 71 trustedDER.len = mozilla::ArrayLength(xpcshellRoot);
michael@0 72 break;
michael@0 73
michael@0 74 default:
michael@0 75 PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
michael@0 76 return SECFailure;
michael@0 77 }
michael@0 78
michael@0 79 mTrustedRoot = CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
michael@0 80 &trustedDER, nullptr, false, true);
michael@0 81 if (!mTrustedRoot) {
michael@0 82 return SECFailure;
michael@0 83 }
michael@0 84
michael@0 85 return SECSuccess;
michael@0 86 }
michael@0 87
michael@0 88 SECStatus
michael@0 89 AppTrustDomain::FindPotentialIssuers(const SECItem* encodedIssuerName,
michael@0 90 PRTime time,
michael@0 91 /*out*/ mozilla::pkix::ScopedCERTCertList& results)
michael@0 92 {
michael@0 93 MOZ_ASSERT(mTrustedRoot);
michael@0 94 if (!mTrustedRoot) {
michael@0 95 PR_SetError(PR_INVALID_STATE_ERROR, 0);
michael@0 96 return SECFailure;
michael@0 97 }
michael@0 98
michael@0 99 results = CERT_CreateSubjectCertList(nullptr, CERT_GetDefaultCertDB(),
michael@0 100 encodedIssuerName, time, true);
michael@0 101 return SECSuccess;
michael@0 102 }
michael@0 103
michael@0 104 SECStatus
michael@0 105 AppTrustDomain::GetCertTrust(EndEntityOrCA endEntityOrCA,
michael@0 106 SECOidTag policy,
michael@0 107 const CERTCertificate* candidateCert,
michael@0 108 /*out*/ TrustLevel* trustLevel)
michael@0 109 {
michael@0 110 MOZ_ASSERT(policy == SEC_OID_X509_ANY_POLICY);
michael@0 111 MOZ_ASSERT(candidateCert);
michael@0 112 MOZ_ASSERT(trustLevel);
michael@0 113 MOZ_ASSERT(mTrustedRoot);
michael@0 114 if (!candidateCert || !trustLevel || policy != SEC_OID_X509_ANY_POLICY) {
michael@0 115 PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
michael@0 116 return SECFailure;
michael@0 117 }
michael@0 118 if (!mTrustedRoot) {
michael@0 119 PR_SetError(PR_INVALID_STATE_ERROR, 0);
michael@0 120 return SECFailure;
michael@0 121 }
michael@0 122
michael@0 123 // Handle active distrust of the certificate.
michael@0 124 CERTCertTrust trust;
michael@0 125 if (CERT_GetCertTrust(candidateCert, &trust) == SECSuccess) {
michael@0 126 PRUint32 flags = SEC_GET_TRUST_FLAGS(&trust, trustObjectSigning);
michael@0 127
michael@0 128 // For DISTRUST, we use the CERTDB_TRUSTED or CERTDB_TRUSTED_CA bit,
michael@0 129 // because we can have active distrust for either type of cert. Note that
michael@0 130 // CERTDB_TERMINAL_RECORD means "stop trying to inherit trust" so if the
michael@0 131 // relevant trust bit isn't set then that means the cert must be considered
michael@0 132 // distrusted.
michael@0 133 PRUint32 relevantTrustBit = endEntityOrCA == MustBeCA
michael@0 134 ? CERTDB_TRUSTED_CA
michael@0 135 : CERTDB_TRUSTED;
michael@0 136 if (((flags & (relevantTrustBit | CERTDB_TERMINAL_RECORD)))
michael@0 137 == CERTDB_TERMINAL_RECORD) {
michael@0 138 *trustLevel = ActivelyDistrusted;
michael@0 139 return SECSuccess;
michael@0 140 }
michael@0 141
michael@0 142 #ifdef MOZ_B2G_CERTDATA
michael@0 143 // XXX(Bug 972201): We have to allow the old way of supporting additional
michael@0 144 // roots until we fix bug 889744. Remove this along with the rest of the
michael@0 145 // MOZ_B2G_CERTDATA stuff.
michael@0 146
michael@0 147 // For TRUST, we only use the CERTDB_TRUSTED_CA bit, because Gecko hasn't
michael@0 148 // needed to consider end-entity certs to be their own trust anchors since
michael@0 149 // Gecko implemented nsICertOverrideService.
michael@0 150 if (flags & CERTDB_TRUSTED_CA) {
michael@0 151 *trustLevel = TrustAnchor;
michael@0 152 return SECSuccess;
michael@0 153 }
michael@0 154 #endif
michael@0 155 }
michael@0 156
michael@0 157 // mTrustedRoot is the only trust anchor for this validation.
michael@0 158 if (CERT_CompareCerts(mTrustedRoot.get(), candidateCert)) {
michael@0 159 *trustLevel = TrustAnchor;
michael@0 160 return SECSuccess;
michael@0 161 }
michael@0 162
michael@0 163 *trustLevel = InheritsTrust;
michael@0 164 return SECSuccess;
michael@0 165 }
michael@0 166
michael@0 167 SECStatus
michael@0 168 AppTrustDomain::VerifySignedData(const CERTSignedData* signedData,
michael@0 169 const CERTCertificate* cert)
michael@0 170 {
michael@0 171 return ::mozilla::pkix::VerifySignedData(signedData, cert, mPinArg);
michael@0 172 }
michael@0 173
michael@0 174 SECStatus
michael@0 175 AppTrustDomain::CheckRevocation(EndEntityOrCA,
michael@0 176 const CERTCertificate*,
michael@0 177 /*const*/ CERTCertificate*,
michael@0 178 PRTime time,
michael@0 179 /*optional*/ const SECItem*)
michael@0 180 {
michael@0 181 // We don't currently do revocation checking. If we need to distrust an Apps
michael@0 182 // certificate, we will use the active distrust mechanism.
michael@0 183 return SECSuccess;
michael@0 184 }
michael@0 185
michael@0 186 } }

mercurial