1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/apps/AppTrustDomain.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,186 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifdef MOZ_LOGGING 1.11 +#define FORCE_PR_LOG 1 1.12 +#endif 1.13 + 1.14 +#include "AppTrustDomain.h" 1.15 +#include "certdb.h" 1.16 +#include "pkix/pkix.h" 1.17 +#include "mozilla/ArrayUtils.h" 1.18 +#include "nsIX509CertDB.h" 1.19 +#include "prerror.h" 1.20 +#include "secerr.h" 1.21 + 1.22 +// Generated in Makefile.in 1.23 +#include "marketplace-prod-public.inc" 1.24 +#include "marketplace-prod-reviewers.inc" 1.25 +#include "marketplace-dev-public.inc" 1.26 +#include "marketplace-dev-reviewers.inc" 1.27 +#include "xpcshell.inc" 1.28 + 1.29 +using namespace mozilla::pkix; 1.30 + 1.31 +#ifdef PR_LOGGING 1.32 +extern PRLogModuleInfo* gPIPNSSLog; 1.33 +#endif 1.34 + 1.35 +namespace mozilla { namespace psm { 1.36 + 1.37 +AppTrustDomain::AppTrustDomain(void* pinArg) 1.38 + : mPinArg(pinArg) 1.39 +{ 1.40 +} 1.41 + 1.42 +SECStatus 1.43 +AppTrustDomain::SetTrustedRoot(AppTrustedRoot trustedRoot) 1.44 +{ 1.45 + SECItem trustedDER; 1.46 + 1.47 + // Load the trusted certificate into the in-memory NSS database so that 1.48 + // CERT_CreateSubjectCertList can find it. 1.49 + 1.50 + switch (trustedRoot) 1.51 + { 1.52 + case nsIX509CertDB::AppMarketplaceProdPublicRoot: 1.53 + trustedDER.data = const_cast<uint8_t*>(marketplaceProdPublicRoot); 1.54 + trustedDER.len = mozilla::ArrayLength(marketplaceProdPublicRoot); 1.55 + break; 1.56 + 1.57 + case nsIX509CertDB::AppMarketplaceProdReviewersRoot: 1.58 + trustedDER.data = const_cast<uint8_t*>(marketplaceProdReviewersRoot); 1.59 + trustedDER.len = mozilla::ArrayLength(marketplaceProdReviewersRoot); 1.60 + break; 1.61 + 1.62 + case nsIX509CertDB::AppMarketplaceDevPublicRoot: 1.63 + trustedDER.data = const_cast<uint8_t*>(marketplaceDevPublicRoot); 1.64 + trustedDER.len = mozilla::ArrayLength(marketplaceDevPublicRoot); 1.65 + break; 1.66 + 1.67 + case nsIX509CertDB::AppMarketplaceDevReviewersRoot: 1.68 + trustedDER.data = const_cast<uint8_t*>(marketplaceDevReviewersRoot); 1.69 + trustedDER.len = mozilla::ArrayLength(marketplaceDevReviewersRoot); 1.70 + break; 1.71 + 1.72 + case nsIX509CertDB::AppXPCShellRoot: 1.73 + trustedDER.data = const_cast<uint8_t*>(xpcshellRoot); 1.74 + trustedDER.len = mozilla::ArrayLength(xpcshellRoot); 1.75 + break; 1.76 + 1.77 + default: 1.78 + PR_SetError(SEC_ERROR_INVALID_ARGS, 0); 1.79 + return SECFailure; 1.80 + } 1.81 + 1.82 + mTrustedRoot = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), 1.83 + &trustedDER, nullptr, false, true); 1.84 + if (!mTrustedRoot) { 1.85 + return SECFailure; 1.86 + } 1.87 + 1.88 + return SECSuccess; 1.89 +} 1.90 + 1.91 +SECStatus 1.92 +AppTrustDomain::FindPotentialIssuers(const SECItem* encodedIssuerName, 1.93 + PRTime time, 1.94 + /*out*/ mozilla::pkix::ScopedCERTCertList& results) 1.95 +{ 1.96 + MOZ_ASSERT(mTrustedRoot); 1.97 + if (!mTrustedRoot) { 1.98 + PR_SetError(PR_INVALID_STATE_ERROR, 0); 1.99 + return SECFailure; 1.100 + } 1.101 + 1.102 + results = CERT_CreateSubjectCertList(nullptr, CERT_GetDefaultCertDB(), 1.103 + encodedIssuerName, time, true); 1.104 + return SECSuccess; 1.105 +} 1.106 + 1.107 +SECStatus 1.108 +AppTrustDomain::GetCertTrust(EndEntityOrCA endEntityOrCA, 1.109 + SECOidTag policy, 1.110 + const CERTCertificate* candidateCert, 1.111 + /*out*/ TrustLevel* trustLevel) 1.112 +{ 1.113 + MOZ_ASSERT(policy == SEC_OID_X509_ANY_POLICY); 1.114 + MOZ_ASSERT(candidateCert); 1.115 + MOZ_ASSERT(trustLevel); 1.116 + MOZ_ASSERT(mTrustedRoot); 1.117 + if (!candidateCert || !trustLevel || policy != SEC_OID_X509_ANY_POLICY) { 1.118 + PR_SetError(SEC_ERROR_INVALID_ARGS, 0); 1.119 + return SECFailure; 1.120 + } 1.121 + if (!mTrustedRoot) { 1.122 + PR_SetError(PR_INVALID_STATE_ERROR, 0); 1.123 + return SECFailure; 1.124 + } 1.125 + 1.126 + // Handle active distrust of the certificate. 1.127 + CERTCertTrust trust; 1.128 + if (CERT_GetCertTrust(candidateCert, &trust) == SECSuccess) { 1.129 + PRUint32 flags = SEC_GET_TRUST_FLAGS(&trust, trustObjectSigning); 1.130 + 1.131 + // For DISTRUST, we use the CERTDB_TRUSTED or CERTDB_TRUSTED_CA bit, 1.132 + // because we can have active distrust for either type of cert. Note that 1.133 + // CERTDB_TERMINAL_RECORD means "stop trying to inherit trust" so if the 1.134 + // relevant trust bit isn't set then that means the cert must be considered 1.135 + // distrusted. 1.136 + PRUint32 relevantTrustBit = endEntityOrCA == MustBeCA 1.137 + ? CERTDB_TRUSTED_CA 1.138 + : CERTDB_TRUSTED; 1.139 + if (((flags & (relevantTrustBit | CERTDB_TERMINAL_RECORD))) 1.140 + == CERTDB_TERMINAL_RECORD) { 1.141 + *trustLevel = ActivelyDistrusted; 1.142 + return SECSuccess; 1.143 + } 1.144 + 1.145 +#ifdef MOZ_B2G_CERTDATA 1.146 + // XXX(Bug 972201): We have to allow the old way of supporting additional 1.147 + // roots until we fix bug 889744. Remove this along with the rest of the 1.148 + // MOZ_B2G_CERTDATA stuff. 1.149 + 1.150 + // For TRUST, we only use the CERTDB_TRUSTED_CA bit, because Gecko hasn't 1.151 + // needed to consider end-entity certs to be their own trust anchors since 1.152 + // Gecko implemented nsICertOverrideService. 1.153 + if (flags & CERTDB_TRUSTED_CA) { 1.154 + *trustLevel = TrustAnchor; 1.155 + return SECSuccess; 1.156 + } 1.157 +#endif 1.158 + } 1.159 + 1.160 + // mTrustedRoot is the only trust anchor for this validation. 1.161 + if (CERT_CompareCerts(mTrustedRoot.get(), candidateCert)) { 1.162 + *trustLevel = TrustAnchor; 1.163 + return SECSuccess; 1.164 + } 1.165 + 1.166 + *trustLevel = InheritsTrust; 1.167 + return SECSuccess; 1.168 +} 1.169 + 1.170 +SECStatus 1.171 +AppTrustDomain::VerifySignedData(const CERTSignedData* signedData, 1.172 + const CERTCertificate* cert) 1.173 +{ 1.174 + return ::mozilla::pkix::VerifySignedData(signedData, cert, mPinArg); 1.175 +} 1.176 + 1.177 +SECStatus 1.178 +AppTrustDomain::CheckRevocation(EndEntityOrCA, 1.179 + const CERTCertificate*, 1.180 + /*const*/ CERTCertificate*, 1.181 + PRTime time, 1.182 + /*optional*/ const SECItem*) 1.183 +{ 1.184 + // We don't currently do revocation checking. If we need to distrust an Apps 1.185 + // certificate, we will use the active distrust mechanism. 1.186 + return SECSuccess; 1.187 +} 1.188 + 1.189 +} }