示例#1
0
SECStatus
AppTrustDomain::GetCertTrust(EndEntityOrCA endEntityOrCA,
                             const CertPolicyId& policy,
                             const SECItem& candidateCertDER,
                     /*out*/ TrustLevel* trustLevel)
{
  MOZ_ASSERT(policy.IsAnyPolicy());
  MOZ_ASSERT(trustLevel);
  MOZ_ASSERT(mTrustedRoot);
  if (!trustLevel || !policy.IsAnyPolicy()) {
    PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
    return SECFailure;
  }
  if (!mTrustedRoot) {
    PR_SetError(PR_INVALID_STATE_ERROR, 0);
    return SECFailure;
  }

  // Handle active distrust of the certificate.

  // XXX: This would be cleaner and more efficient if we could get the trust
  // information without constructing a CERTCertificate here, but NSS doesn't
  // expose it in any other easy-to-use fashion.
  ScopedCERTCertificate candidateCert(
    CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
                            const_cast<SECItem*>(&candidateCertDER), nullptr,
                            false, true));
  if (!candidateCert) {
    return SECFailure;
  }

  CERTCertTrust trust;
  if (CERT_GetCertTrust(candidateCert.get(), &trust) == SECSuccess) {
    PRUint32 flags = SEC_GET_TRUST_FLAGS(&trust, trustObjectSigning);

    // For DISTRUST, we use the CERTDB_TRUSTED or CERTDB_TRUSTED_CA bit,
    // because we can have active distrust for either type of cert. Note that
    // CERTDB_TERMINAL_RECORD means "stop trying to inherit trust" so if the
    // relevant trust bit isn't set then that means the cert must be considered
    // distrusted.
    PRUint32 relevantTrustBit = endEntityOrCA == EndEntityOrCA::MustBeCA
                              ? CERTDB_TRUSTED_CA
                              : CERTDB_TRUSTED;
    if (((flags & (relevantTrustBit | CERTDB_TERMINAL_RECORD)))
            == CERTDB_TERMINAL_RECORD) {
      *trustLevel = TrustLevel::ActivelyDistrusted;
      return SECSuccess;
    }
  }

  // mTrustedRoot is the only trust anchor for this validation.
  if (CERT_CompareCerts(mTrustedRoot.get(), candidateCert.get())) {
    *trustLevel = TrustLevel::TrustAnchor;
    return SECSuccess;
  }

  *trustLevel = TrustLevel::InheritsTrust;
  return SECSuccess;
}
示例#2
0
static void
addToCertListIfTrusted(CERTCertList* certList, CERTCertificate* cert) {
  CERTCertTrust nssTrust;
  if (CERT_GetCertTrust(cert, &nssTrust) != SECSuccess) {
    return;
  }
  unsigned int flags = SEC_GET_TRUST_FLAGS(&nssTrust, trustSSL);

  if (flags & CERTDB_TRUSTED_CA) {
    CERT_AddCertToListTail(certList, CERT_DupCertificate(cert));
  }
}
SECStatus
NSSCertDBTrustDomain::GetCertTrust(EndEntityOrCA endEntityOrCA,
                                   const CERTCertificate* candidateCert,
                                   /*out*/ TrustLevel* trustLevel)
{
  PORT_Assert(candidateCert);
  PORT_Assert(trustLevel);
  if (!candidateCert || !trustLevel) {
    PORT_SetError(SEC_ERROR_INVALID_ARGS);
    return SECFailure;
  }

  // XXX: CERT_GetCertTrust seems to be abusing SECStatus as a boolean, where
  // SECSuccess means that there is a trust record and SECFailure means there
  // is not a trust record. I looked at NSS's internal uses of
  // CERT_GetCertTrust, and all that code uses the result as a boolean meaning
  // "We have a trust record."
  CERTCertTrust trust;
  if (CERT_GetCertTrust(candidateCert, &trust) == SECSuccess) {
    PRUint32 flags = SEC_GET_TRUST_FLAGS(&trust, mCertDBTrustType);

    // For DISTRUST, we use the CERTDB_TRUSTED or CERTDB_TRUSTED_CA bit,
    // because we can have active distrust for either type of cert. Note that
    // CERTDB_TERMINAL_RECORD means "stop trying to inherit trust" so if the
    // relevant trust bit isn't set then that means the cert must be considered
    // distrusted.
    PRUint32 relevantTrustBit = endEntityOrCA == MustBeCA ? CERTDB_TRUSTED_CA
                                                          : CERTDB_TRUSTED;
    if (((flags & (relevantTrustBit|CERTDB_TERMINAL_RECORD)))
            == CERTDB_TERMINAL_RECORD) {
      *trustLevel = ActivelyDistrusted;
      return SECSuccess;
    }

    // For TRUST, we only use the CERTDB_TRUSTED_CA bit, because Gecko hasn't
    // needed to consider end-entity certs to be their own trust anchors since
    // Gecko implemented nsICertOverrideService.
    if (flags & CERTDB_TRUSTED_CA) {
      *trustLevel = TrustAnchor;
      return SECSuccess;
    }
  }

  *trustLevel = InheritsTrust;
  return SECSuccess;
}
示例#4
0
static PRBool
nss3certificate_isTrustedForUsage(nssDecodedCert *dc, const NSSUsage *usage)
{
    CERTCertificate *cc;
    PRBool ca;
    SECStatus secrv;
    unsigned int requiredFlags;
    unsigned int trustFlags;
    SECTrustType trustType;
    CERTCertTrust trust;

    /* This is for NSS 3.3 functions that do not specify a usage */
    if (usage->anyUsage) {
	return PR_FALSE;  /* XXX is this right? */
    }
    cc = (CERTCertificate *)dc->data;
    ca = usage->nss3lookingForCA;
    if (!ca) {
	PRBool trusted;
	unsigned int failedFlags;
	secrv = cert_CheckLeafTrust(cc, usage->nss3usage,
				    &failedFlags, &trusted);
	return secrv == SECSuccess && trusted;
    }
    secrv = CERT_TrustFlagsForCACertUsage(usage->nss3usage, &requiredFlags,
					  &trustType);
    if (secrv != SECSuccess) {
	return PR_FALSE;
    }
    secrv = CERT_GetCertTrust(cc, &trust);
    if (secrv != SECSuccess) {
	return PR_FALSE;
    }
    if (trustType == trustTypeNone) {
	/* normally trustTypeNone usages accept any of the given trust bits
	 * being on as acceptable. */
	trustFlags = trust.sslFlags | trust.emailFlags |
		     trust.objectSigningFlags;
    } else {
	trustFlags = SEC_GET_TRUST_FLAGS(&trust, trustType);
    }
    return (trustFlags & requiredFlags) == requiredFlags;
}
示例#5
0
SECStatus
AppTrustDomain::GetCertTrust(EndEntityOrCA endEntityOrCA,
                             SECOidTag policy,
                             const CERTCertificate* candidateCert,
                             /*out*/ TrustLevel* trustLevel)
{
    MOZ_ASSERT(policy == SEC_OID_X509_ANY_POLICY);
    MOZ_ASSERT(candidateCert);
    MOZ_ASSERT(trustLevel);
    MOZ_ASSERT(mTrustedRoot);
    if (!candidateCert || !trustLevel || policy != SEC_OID_X509_ANY_POLICY) {
        PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
        return SECFailure;
    }
    if (!mTrustedRoot) {
        PR_SetError(PR_INVALID_STATE_ERROR, 0);
        return SECFailure;
    }

    // Handle active distrust of the certificate.
    CERTCertTrust trust;
    if (CERT_GetCertTrust(candidateCert, &trust) == SECSuccess) {
        PRUint32 flags = SEC_GET_TRUST_FLAGS(&trust, trustObjectSigning);

        // For DISTRUST, we use the CERTDB_TRUSTED or CERTDB_TRUSTED_CA bit,
        // because we can have active distrust for either type of cert. Note that
        // CERTDB_TERMINAL_RECORD means "stop trying to inherit trust" so if the
        // relevant trust bit isn't set then that means the cert must be considered
        // distrusted.
        PRUint32 relevantTrustBit = endEntityOrCA == MustBeCA
                                    ? CERTDB_TRUSTED_CA
                                    : CERTDB_TRUSTED;
        if (((flags & (relevantTrustBit | CERTDB_TERMINAL_RECORD)))
                == CERTDB_TERMINAL_RECORD) {
            *trustLevel = ActivelyDistrusted;
            return SECSuccess;
        }

#ifdef MOZ_B2G_CERTDATA
        // XXX(Bug 972201): We have to allow the old way of supporting additional
        // roots until we fix bug 889744. Remove this along with the rest of the
        // MOZ_B2G_CERTDATA stuff.

        // For TRUST, we only use the CERTDB_TRUSTED_CA bit, because Gecko hasn't
        // needed to consider end-entity certs to be their own trust anchors since
        // Gecko implemented nsICertOverrideService.
        if (flags & CERTDB_TRUSTED_CA) {
            *trustLevel = TrustAnchor;
            return SECSuccess;
        }
#endif
    }

    // mTrustedRoot is the only trust anchor for this validation.
    if (CERT_CompareCerts(mTrustedRoot.get(), candidateCert)) {
        *trustLevel = TrustAnchor;
        return SECSuccess;
    }

    *trustLevel = InheritsTrust;
    return SECSuccess;
}