Esempio n. 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;
}
Esempio n. 2
0
static CERTCertificate *
stan_GetCERTCertificate(NSSCertificate *c, PRBool forceUpdate)
{
    nssDecodedCert *dc = NULL;
    CERTCertificate *cc = NULL;
    CERTCertTrust certTrust;

    nssPKIObject_Lock(&c->object);

    dc = c->decoding;
    if (!dc) {
	dc = nssDecodedPKIXCertificate_Create(NULL, &c->encoding);
	if (!dc) {
            goto loser;
        }
	cc = (CERTCertificate *)dc->data;
	PORT_Assert(cc); /* software error */
	if (!cc) {
	    nssDecodedPKIXCertificate_Destroy(dc);
	    nss_SetError(NSS_ERROR_INTERNAL_ERROR);
	    goto loser;
	}
    	PORT_Assert(!c->decoding); 
	if (!c->decoding) {
	    c->decoding = dc;
	} else { 
            /* this should never happen. Fail. */
	    nssDecodedPKIXCertificate_Destroy(dc);
	    nss_SetError(NSS_ERROR_INTERNAL_ERROR);
            goto loser;
	}
    }
    cc = (CERTCertificate *)dc->data;
    PORT_Assert(cc);
    if (!cc) {
        nss_SetError(NSS_ERROR_INTERNAL_ERROR);
        goto loser;
    }
    if (!cc->nssCertificate || forceUpdate) {
        fill_CERTCertificateFields(c, cc, forceUpdate);
    } else if (CERT_GetCertTrust(cc, &certTrust) != SECSuccess &&
               !c->object.cryptoContext) {
        /* if it's a perm cert, it might have been stored before the
         * trust, so look for the trust again.  But a temp cert can be
         * ignored.
         */
        CERTCertTrust* trust = NULL;
        trust = nssTrust_GetCERTCertTrustForCert(c, cc);

        CERT_LockCertTrust(cc);
        cc->trust = trust;
        CERT_UnlockCertTrust(cc);
    }

  loser:
    nssPKIObject_Unlock(&c->object);
    return cc;
}
Esempio n. 3
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));
  }
}
Esempio n. 4
0
NS_IMETHODIMP 
nsNSSCertificateDB::IsCertTrusted(nsIX509Cert *cert, 
                                  PRUint32 certType,
                                  PRUint32 trustType,
                                  PRBool *_isTrusted)
{
  NS_ENSURE_ARG_POINTER(_isTrusted);
  *_isTrusted = PR_FALSE;

  nsNSSShutDownPreventionLock locker;
  SECStatus srv;
  nsCOMPtr<nsIX509Cert2> pipCert = do_QueryInterface(cert);
  CERTCertificate *nsscert = pipCert->GetCert();
  CERTCertTrust nsstrust;
  srv = CERT_GetCertTrust(nsscert, &nsstrust);
  if (srv != SECSuccess)
    return NS_ERROR_FAILURE;

  nsNSSCertTrust trust(&nsstrust);
  CERT_DestroyCertificate(nsscert);
  if (certType == nsIX509Cert::CA_CERT) {
    if (trustType & nsIX509CertDB::TRUSTED_SSL) {
      *_isTrusted = trust.HasTrustedCA(PR_TRUE, PR_FALSE, PR_FALSE);
    } else if (trustType & nsIX509CertDB::TRUSTED_EMAIL) {
      *_isTrusted = trust.HasTrustedCA(PR_FALSE, PR_TRUE, PR_FALSE);
    } else if (trustType & nsIX509CertDB::TRUSTED_OBJSIGN) {
      *_isTrusted = trust.HasTrustedCA(PR_FALSE, PR_FALSE, PR_TRUE);
    } else {
      return NS_ERROR_FAILURE;
    }
  } else if (certType == nsIX509Cert::SERVER_CERT) {
    if (trustType & nsIX509CertDB::TRUSTED_SSL) {
      *_isTrusted = trust.HasTrustedPeer(PR_TRUE, PR_FALSE, PR_FALSE);
    } else if (trustType & nsIX509CertDB::TRUSTED_EMAIL) {
      *_isTrusted = trust.HasTrustedPeer(PR_FALSE, PR_TRUE, PR_FALSE);
    } else if (trustType & nsIX509CertDB::TRUSTED_OBJSIGN) {
      *_isTrusted = trust.HasTrustedPeer(PR_FALSE, PR_FALSE, PR_TRUE);
    } else {
      return NS_ERROR_FAILURE;
    }
  } else if (certType == nsIX509Cert::EMAIL_CERT) {
    if (trustType & nsIX509CertDB::TRUSTED_SSL) {
      *_isTrusted = trust.HasTrustedPeer(PR_TRUE, PR_FALSE, PR_FALSE);
    } else if (trustType & nsIX509CertDB::TRUSTED_EMAIL) {
      *_isTrusted = trust.HasTrustedPeer(PR_FALSE, PR_TRUE, PR_FALSE);
    } else if (trustType & nsIX509CertDB::TRUSTED_OBJSIGN) {
      *_isTrusted = trust.HasTrustedPeer(PR_FALSE, PR_FALSE, PR_TRUE);
    } else {
      return NS_ERROR_FAILURE;
    }
  } /* user: ignore */
  return NS_OK;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
static SECStatus
CollectDistNames( CERTCertificate *cert, SECItem *k, void *data)
{
    CERTDistNames *names;
    PRBool saveit = PR_FALSE;
    CERTCertTrust trust;
    dnameNode *node;
    int len;
    
    names = (CERTDistNames *)data;
    
    if ( CERT_GetCertTrust(cert, &trust) == SECSuccess ) {
	/* only collect names of CAs trusted for issuing SSL clients */
	if (  trust.sslFlags &  CERTDB_TRUSTED_CLIENT_CA )  {
	    saveit = PR_TRUE;
	}
    }

    if ( saveit ) {
	/* allocate the node */
	node = (dnameNode*)PORT_ArenaAlloc(names->arena, sizeof(dnameNode));
	if ( node == NULL ) {
	    return(SECFailure);
	}

	/* copy the name */
	node->name.len = len = cert->derSubject.len;
	node->name.type = siBuffer;
	node->name.data = (unsigned char*)PORT_ArenaAlloc(names->arena, len);
	if ( node->name.data == NULL ) {
	    return(SECFailure);
	}
	PORT_Memcpy(node->name.data, cert->derSubject.data, len);

	/* link it into the list */
	node->next = (dnameNode *)names->head;
	names->head = (void *)node;

	/* bump the count */
	names->nnames++;
    }
    
    return(SECSuccess);
}
Esempio n. 7
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;
}
// Based on nsNSSCertificateDB::SetCertTrust.
bool
SetCertTrust(const net::X509Certificate* cert,
             net::CertType type,
             net::NSSCertDatabase::TrustBits trustBits)
{
  const unsigned kSSLTrustBits = net::NSSCertDatabase::TRUSTED_SSL |
      net::NSSCertDatabase::DISTRUSTED_SSL;
  const unsigned kEmailTrustBits = net::NSSCertDatabase::TRUSTED_EMAIL |
      net::NSSCertDatabase::DISTRUSTED_EMAIL;
  const unsigned kObjSignTrustBits = net::NSSCertDatabase::TRUSTED_OBJ_SIGN |
      net::NSSCertDatabase::DISTRUSTED_OBJ_SIGN;
  if ((trustBits & kSSLTrustBits) == kSSLTrustBits ||
      (trustBits & kEmailTrustBits) == kEmailTrustBits ||
      (trustBits & kObjSignTrustBits) == kObjSignTrustBits) {
    LOG(ERROR) << "SetCertTrust called with conflicting trust bits "
               << trustBits;
    NOTREACHED();
    return false;
  }

  SECStatus srv;
  CERTCertificate *nsscert = cert->os_cert_handle();
  if (type == net::CA_CERT) {
    // Note that we start with CERTDB_VALID_CA for default trust and explicit
    // trust, but explicitly distrusted usages will be set to
    // CERTDB_TERMINAL_RECORD only.
    CERTCertTrust trust = {CERTDB_VALID_CA, CERTDB_VALID_CA, CERTDB_VALID_CA};

    if (trustBits & net::NSSCertDatabase::DISTRUSTED_SSL)
      trust.sslFlags = CERTDB_TERMINAL_RECORD;
    else if (trustBits & net::NSSCertDatabase::TRUSTED_SSL)
      trust.sslFlags |= CERTDB_TRUSTED_CA | CERTDB_TRUSTED_CLIENT_CA;

    if (trustBits & net::NSSCertDatabase::DISTRUSTED_EMAIL)
      trust.emailFlags = CERTDB_TERMINAL_RECORD;
    else if (trustBits & net::NSSCertDatabase::TRUSTED_EMAIL)
      trust.emailFlags |= CERTDB_TRUSTED_CA | CERTDB_TRUSTED_CLIENT_CA;

    if (trustBits & net::NSSCertDatabase::DISTRUSTED_OBJ_SIGN)
      trust.objectSigningFlags = CERTDB_TERMINAL_RECORD;
    else if (trustBits & net::NSSCertDatabase::TRUSTED_OBJ_SIGN)
      trust.objectSigningFlags |= CERTDB_TRUSTED_CA | CERTDB_TRUSTED_CLIENT_CA;

    srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), nsscert, &trust);
  } else if (type == net::SERVER_CERT) {
    CERTCertTrust trust = {0};
    // We only modify the sslFlags, so copy the other flags.
    CERT_GetCertTrust(nsscert, &trust);
    trust.sslFlags = 0;

    if (trustBits & net::NSSCertDatabase::DISTRUSTED_SSL)
      trust.sslFlags |= CERTDB_TERMINAL_RECORD;
    else if (trustBits & net::NSSCertDatabase::TRUSTED_SSL)
      trust.sslFlags |= CERTDB_TRUSTED | CERTDB_TERMINAL_RECORD;

    srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), nsscert, &trust);
  } else {
    // ignore user and email/unknown certs
    return true;
  }
  if (srv != SECSuccess)
    LOG(ERROR) << "SetCertTrust failed with error " << PORT_GetError();
  return srv == SECSuccess;
}
Esempio n. 9
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;
}