Example #1
0
/* boolean hasMoreElements (); */
NS_IMETHODIMP
nsNSSCertListEnumerator::HasMoreElements(bool *_retval)
{ 
  NS_ENSURE_TRUE(mCertList, NS_ERROR_FAILURE);

  *_retval = !CERT_LIST_EMPTY(mCertList);
  return NS_OK;
}
CERTCertificateList*
hack_NewCertificateListFromCertList(CERTCertList* list)
{
    CERTCertificateList * chain = NULL;
    PLArenaPool * arena = NULL;
    CERTCertListNode * node;
    int len;

    if (CERT_LIST_EMPTY(list))
        goto loser;

    arena = PORT_NewArena(4096);
    if (arena == NULL)
        goto loser;

    for (len = 0, node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list);
        len++, node = CERT_LIST_NEXT(node)) {
    }

    chain = PORT_ArenaNew(arena, CERTCertificateList);
    if (chain == NULL)
        goto loser;

    chain->certs = PORT_ArenaNewArray(arena, SECItem, len);
    if (!chain->certs)
        goto loser;
    chain->len = len;

    for (len = 0, node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list);
        len++, node = CERT_LIST_NEXT(node)) {
        // Check to see if the last cert to be sent is a self-signed cert,
        // and if so, omit it from the list of certificates. However, if
        // there is only one cert (len == 0), include the cert, as it means
        // the EE cert is self-signed.
        if (len > 0 && (len == chain->len - 1) && node->cert->isRoot) {
            chain->len = len;
            break;
        }
        SECITEM_CopyItem(arena, &chain->certs[len], &node->cert->derCert);
    }

    chain->arena = arena;
    return chain;

loser:
    if (arena) {
        PORT_FreeArena(arena, PR_FALSE);
    }
    return NULL;
}
Example #3
0
Result
IsCertChainRootBuiltInRoot(CERTCertList* chain, bool& result)
{
  if (!chain || CERT_LIST_EMPTY(chain)) {
    return Result::FATAL_ERROR_LIBRARY_FAILURE;
  }
  CERTCertListNode* rootNode = CERT_LIST_TAIL(chain);
  if (!rootNode) {
    return Result::FATAL_ERROR_LIBRARY_FAILURE;
  }
  CERTCertificate* root = rootNode->cert;
  if (!root) {
    return Result::FATAL_ERROR_LIBRARY_FAILURE;
  }
  return IsCertBuiltInRoot(root, result);
}
Example #4
0
/* would not do name in pluto, but dn */
static CERTCertList *get_trust_certlist(CERTCertDBHandle *handle,
				     const char *name)
{
	CERTCertList *trustcl = NULL;
	CERTCertList *tmpcl = NULL;
	CERTCertificate *ca = NULL;
	CERTCertListNode *node = NULL;

	if ((ca = CERT_FindCertByNickname(handle, name)) == NULL) {
		printf("CERT_FindCertByNickname failed %d\n",
				PORT_GetError());
		return NULL;
	}

	if (ca->isRoot) {
		printf("trust anchor: %s\n",ca->subjectName);
		trustcl = CERT_NewCertList();
		CERT_AddCertToListTail(trustcl, ca);
	} else {
		tmpcl = CERT_GetCertChainFromCert(ca, PR_Now(), certUsageAnyCA);
		if (tmpcl == NULL) {
			printf("CERT_GetCertChainFromCert failed %d\n",
					PORT_GetError());
			return NULL;
		}
		for (node = CERT_LIST_HEAD(tmpcl); !CERT_LIST_END(node, tmpcl);
				node = CERT_LIST_NEXT(node)) {
			printf("CERT list: %s\n", node->cert->subjectName);
			if (node->cert->isRoot) {
				trustcl = CERT_NewCertList();
				CERT_AddCertToListTail(trustcl, node->cert);
				break;
			}
		}
	}

	if (trustcl == NULL || CERT_LIST_EMPTY(trustcl)) {
		printf("Trust chain empty!\n");
		return NULL;
	}

	return trustcl;
}
Example #5
0
static CERTCertList *get_all_root_certs(void)
{
	PK11SlotInfo *slot = PK11_GetInternalKeySlot();

	if (slot == NULL)
		return NULL;

	if (PK11_NeedLogin(slot)) {
		SECStatus rv = PK11_Authenticate(slot, PR_TRUE,
				lsw_return_nss_password_file_info());
		if (rv != SECSuccess)
			return NULL;
	}

	CERTCertList *allcerts = PK11_ListCertsInSlot(slot);

	if (allcerts == NULL)
		return NULL;

	CERTCertList *roots = CERT_NewCertList();

	CERTCertListNode *node;

	for (node = CERT_LIST_HEAD(allcerts); !CERT_LIST_END(node, allcerts);
						node = CERT_LIST_NEXT(node)) {
		if (CERT_IsCACert(node->cert, NULL) && node->cert->isRoot) {
			CERT_DupCertificate(node->cert);
			CERT_AddCertToListTail(roots, node->cert);
		}
	}

	CERT_DestroyCertList(allcerts);

	if (roots == NULL || CERT_LIST_EMPTY(roots))
		return NULL;

	return roots;
}
Example #6
0
static CERTCertificate *
common_FindCertByNicknameOrEmailAddrForUsage(CERTCertDBHandle *handle,
                                             const char *name, PRBool anyUsage,
                                             SECCertUsage lookingForUsage)
{
    NSSCryptoContext *cc;
    NSSCertificate *c, *ct;
    CERTCertificate *cert = NULL;
    NSSUsage usage;
    CERTCertList *certlist;

    if (NULL == name) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return NULL;
    }

    usage.anyUsage = anyUsage;

    if (!anyUsage) {
        usage.nss3lookingForCA = PR_FALSE;
        usage.nss3usage = lookingForUsage;
    }

    cc = STAN_GetDefaultCryptoContext();
    ct = NSSCryptoContext_FindBestCertificateByNickname(cc, name, NULL, &usage,
                                                        NULL);
    if (!ct && PORT_Strchr(name, '@') != NULL) {
        char *lowercaseName = CERT_FixupEmailAddr(name);
        if (lowercaseName) {
            ct = NSSCryptoContext_FindBestCertificateByEmail(
                cc, lowercaseName, NULL, &usage, NULL);
            PORT_Free(lowercaseName);
        }
    }

    if (anyUsage) {
        cert = PK11_FindCertFromNickname(name, NULL);
    } else {
        if (ct) {
            /* Does ct really have the required usage? */
            nssDecodedCert *dc;
            dc = nssCertificate_GetDecoding(ct);
            if (!dc->matchUsage(dc, &usage)) {
                CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct));
                ct = NULL;
            }
        }

        certlist = PK11_FindCertsFromNickname(name, NULL);
        if (certlist) {
            SECStatus rv =
                CERT_FilterCertListByUsage(certlist, lookingForUsage, PR_FALSE);
            if (SECSuccess == rv && !CERT_LIST_EMPTY(certlist)) {
                cert = CERT_DupCertificate(CERT_LIST_HEAD(certlist)->cert);
            }
            CERT_DestroyCertList(certlist);
        }
    }

    if (cert) {
        c = get_best_temp_or_perm(ct, STAN_GetNSSCertificate(cert));
        CERT_DestroyCertificate(cert);
        if (ct) {
            CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct));
        }
    } else {
        c = ct;
    }
    return c ? STAN_GetCERTCertificateOrRelease(c) : NULL;
}
Example #7
0
SECStatus
CertVerifier::VerifyCert(CERTCertificate * cert,
                         const SECCertificateUsage usage,
                         const PRTime time,
                         nsIInterfaceRequestor * pinArg,
                         const Flags flags,
                         /*optional out*/ CERTCertList **validationChain,
                         /*optional out*/ SECOidTag *evOidPolicy,
                         /*optional out*/ CERTVerifyLog *verifyLog)
{
  if (!cert) {
    PORT_SetError(SEC_ERROR_INVALID_ARGS);
    return SECFailure;
  }
  if (validationChain) {
    *validationChain = nullptr;
  }
  if (evOidPolicy) {
    *evOidPolicy = SEC_OID_UNKNOWN;
  }

  switch(usage){
    case certificateUsageSSLClient:
    case certificateUsageSSLServer:
    case certificateUsageSSLCA:
    case certificateUsageEmailSigner:
    case certificateUsageEmailRecipient:
    case certificateUsageObjectSigner:
    case certificateUsageStatusResponder:
      break;
    default:
      NS_WARNING("Calling VerifyCert with invalid usage");
      PORT_SetError(SEC_ERROR_INVALID_ARGS);
      return SECFailure;
  }

  ScopedCERTCertList trustAnchors;
  SECStatus rv;
  SECOidTag evPolicy = SEC_OID_UNKNOWN;

#ifdef NSS_NO_LIBPKIX
  return ClassicVerifyCert(cert, usage, time, pinArg, validationChain,
                           verifyLog);
#else
  // Do EV checking only for sslserver usage
  if (usage == certificateUsageSSLServer) {
    SECStatus srv = getFirstEVPolicy(cert, evPolicy);
    if (srv == SECSuccess) {
      if (evPolicy != SEC_OID_UNKNOWN) {
        trustAnchors = getRootsForOid(evPolicy);
      }
      if (!trustAnchors) {
        return SECFailure;
      }
      // pkix ignores an empty trustanchors list and
      // decides then to use the whole set of trust in the DB
      // so we set the evPolicy to unkown in this case
      if (CERT_LIST_EMPTY(trustAnchors)) {
        evPolicy = SEC_OID_UNKNOWN;
      }
    } else {
      // Do not setup EV verification params
      evPolicy = SEC_OID_UNKNOWN;
    }
  }
  
  MOZ_ASSERT_IF(evPolicy != SEC_OID_UNKNOWN, trustAnchors);

  size_t i = 0;
  size_t validationChainLocation = 0;
  size_t validationTrustAnchorLocation = 0;
  CERTValOutParam cvout[4];
  if (verifyLog) {
     cvout[i].type = cert_po_errorLog;
     cvout[i].value.pointer.log = verifyLog;
     ++i;
  }
  if (validationChain) {
    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("VerifyCert: setting up validation chain outparam.\n"));
    validationChainLocation = i;
    cvout[i].type = cert_po_certList;
    cvout[i].value.pointer.cert = nullptr;
    ++i;
    validationTrustAnchorLocation = i;
    cvout[i].type = cert_po_trustAnchor;
    cvout[i].value.pointer.chain = nullptr;
    ++i;
  }
  cvout[i].type = cert_po_end;

  CERTRevocationFlags rev;

  CERTRevocationMethodIndex revPreferredMethods[2];
  rev.leafTests.preferred_methods =
  rev.chainTests.preferred_methods = revPreferredMethods;

  uint64_t revFlagsPerMethod[2];
  rev.leafTests.cert_rev_flags_per_method =
  rev.chainTests.cert_rev_flags_per_method = revFlagsPerMethod;
  rev.leafTests.number_of_preferred_methods =
  rev.chainTests.number_of_preferred_methods = 1;

  rev.leafTests.number_of_defined_methods =
  rev.chainTests.number_of_defined_methods = cert_revocation_method_ocsp + 1;

  const bool localOnly = flags & FLAG_LOCAL_ONLY;
  CERTValInParam cvin[6];

  // Parameters for both EV and DV validation
  cvin[0].type = cert_pi_useAIACertFetch;
  cvin[0].value.scalar.b = mMissingCertDownloadEnabled && !localOnly;
  cvin[1].type = cert_pi_revocationFlags;
  cvin[1].value.pointer.revocation = &rev;
  cvin[2].type = cert_pi_date;
  cvin[2].value.scalar.time = time;
  i = 3;
  const size_t evParamLocation = i;

  if (evPolicy != SEC_OID_UNKNOWN) {
    // EV setup!
    // XXX 859872 The current flags are not quite correct. (use
    // of ocsp flags for crl preferences).
    uint64_t ocspRevMethodFlags =
      CERT_REV_M_TEST_USING_THIS_METHOD
      | ((mOCSPDownloadEnabled && !localOnly) ?
          CERT_REV_M_ALLOW_NETWORK_FETCHING : CERT_REV_M_FORBID_NETWORK_FETCHING)
      | CERT_REV_M_ALLOW_IMPLICIT_DEFAULT_SOURCE
      | CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE
      | CERT_REV_M_IGNORE_MISSING_FRESH_INFO
      | CERT_REV_M_STOP_TESTING_ON_FRESH_INFO
      | (mOCSPGETEnabled ? 0 : CERT_REV_M_FORCE_POST_METHOD_FOR_OCSP);

    rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_crl] =
    rev.chainTests.cert_rev_flags_per_method[cert_revocation_method_crl]
      = CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD;

    rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_ocsp] =
    rev.chainTests.cert_rev_flags_per_method[cert_revocation_method_ocsp]
      = ocspRevMethodFlags;

    rev.leafTests.cert_rev_method_independent_flags =
    rev.chainTests.cert_rev_method_independent_flags =
      // avoiding the network is good, let's try local first
      CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST
      // is overall revocation requirement strict or relaxed?
      |  CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE
      ;

    rev.leafTests.preferred_methods[0] =
    rev.chainTests.preferred_methods[0] = cert_revocation_method_ocsp;

    cvin[i].type = cert_pi_policyOID;
    cvin[i].value.arraySize = 1;
    cvin[i].value.array.oids = &evPolicy;
    ++i;
    MOZ_ASSERT(trustAnchors);
    cvin[i].type = cert_pi_trustAnchors;
    cvin[i].value.pointer.chain = trustAnchors;
    ++i;

    cvin[i].type = cert_pi_end;

    rv = CERT_PKIXVerifyCert(cert, usage, cvin, cvout, pinArg);
    if (rv == SECSuccess) {
      if (evOidPolicy) {
        *evOidPolicy = evPolicy;
      }
      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
             ("VerifyCert: successful CERT_PKIXVerifyCert(ev) \n"));
      goto pkix_done;
    }
    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
           ("VerifyCert: failed CERT_PKIXVerifyCert(ev)\n"));

    if (validationChain && *validationChain) {
      // There SHOULD not be a validation chain on failure, asserion here for
      // the debug builds AND a fallback for production builds
      MOZ_ASSERT(false,
                 "certPKIXVerifyCert returned failure AND a validationChain");
      CERT_DestroyCertList(*validationChain);
      *validationChain = nullptr;
    }

    if (verifyLog) {
      // Cleanup the log so that it is ready the the next validation
      CERTVerifyLogNode *i_node;
      for (i_node = verifyLog->head; i_node; i_node = i_node->next) {
         //destroy cert if any.
         if (i_node->cert) {
           CERT_DestroyCertificate(i_node->cert);
         }
         // No need to cleanup the actual nodes in the arena.
      }
      verifyLog->count = 0;
      verifyLog->head = nullptr;
      verifyLog->tail = nullptr;
    }

  }

  if (!nsNSSComponent::globalConstFlagUsePKIXVerification){
    // XXX: we do not care about the localOnly flag (currently) as the
    // caller that wants localOnly should disable and reenable the fetching.
    return ClassicVerifyCert(cert, usage, time, pinArg, validationChain,
                             verifyLog);
  }

  // The current flags check the chain the same way as the leafs
  rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_crl] =
  rev.chainTests.cert_rev_flags_per_method[cert_revocation_method_crl] =
    // implicit default source - makes no sense for CRLs
    CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE

    // let's not stop on fresh CRL. If OCSP is enabled, too, let's check it
    | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO

    // no fresh CRL? well, let other flag decide whether to fail or not
    | CERT_REV_M_IGNORE_MISSING_FRESH_INFO

    // testing using local CRLs is always allowed
    | CERT_REV_M_TEST_USING_THIS_METHOD

    // no local crl and don't know where to get it from? ignore
    | CERT_REV_M_SKIP_TEST_ON_MISSING_SOURCE

    // crl download based on parameter
    | ((mCRLDownloadEnabled && !localOnly) ?
        CERT_REV_M_ALLOW_NETWORK_FETCHING : CERT_REV_M_FORBID_NETWORK_FETCHING)
    ;

  rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_ocsp] =
  rev.chainTests.cert_rev_flags_per_method[cert_revocation_method_ocsp] =
    // use OCSP
      CERT_REV_M_TEST_USING_THIS_METHOD

    // if app has a default OCSP responder configured, let's use it
    | CERT_REV_M_ALLOW_IMPLICIT_DEFAULT_SOURCE

    // of course OCSP doesn't work without a source. let's accept such certs
    | CERT_REV_M_SKIP_TEST_ON_MISSING_SOURCE

    // if ocsp is required stop on lack of freshness
    | (mOCSPStrict ?
       CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO : CERT_REV_M_IGNORE_MISSING_FRESH_INFO)

    // ocsp success is sufficient
    | CERT_REV_M_STOP_TESTING_ON_FRESH_INFO

    // ocsp enabled controls network fetching, too
    | ((mOCSPDownloadEnabled && !localOnly) ?
        CERT_REV_M_ALLOW_NETWORK_FETCHING : CERT_REV_M_FORBID_NETWORK_FETCHING)
    
    | (mOCSPGETEnabled ? 0 : CERT_REV_M_FORCE_POST_METHOD_FOR_OCSP);
    ;

  rev.leafTests.preferred_methods[0] =
  rev.chainTests.preferred_methods[0] = cert_revocation_method_ocsp;

  rev.leafTests.cert_rev_method_independent_flags =
  rev.chainTests.cert_rev_method_independent_flags =
    // avoiding the network is good, let's try local first
    CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST

    // is overall revocation requirement strict or relaxed?
    | (mRequireRevocationInfo ?
       CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE : CERT_REV_MI_NO_OVERALL_INFO_REQUIREMENT)
    ;

  // Skip EV parameters
  cvin[evParamLocation].type = cert_pi_end;

  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("VerifyCert: calling CERT_PKIXVerifyCert(dv) \n"));
  rv = CERT_PKIXVerifyCert(cert, usage, cvin, cvout, pinArg);

pkix_done:
  if (validationChain) {
    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("VerifyCert: validation chain requested\n"));
    ScopedCERTCertificate trustAnchor(cvout[validationTrustAnchorLocation].value.pointer.cert);

    if (rv == SECSuccess) {
      if (! cvout[validationChainLocation].value.pointer.chain) {
        PR_SetError(PR_UNKNOWN_ERROR, 0);
        return SECFailure;
      }
      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("VerifyCert: I have a chain\n"));
      *validationChain = cvout[validationChainLocation].value.pointer.chain;
      if (trustAnchor) {
        // we should only add the issuer to the chain if it is not already
        // present. On CA cert checking, the issuer is the same cert, so in
        // that case we do not add the cert to the chain.
        if (!CERT_CompareCerts(trustAnchor, cert)) {
          PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("VerifyCert:  adding issuer to tail for display\n"));
          // note: rv is reused to catch errors on cert creation!
          ScopedCERTCertificate tempCert(CERT_DupCertificate(trustAnchor));
          rv = CERT_AddCertToListTail(*validationChain, tempCert);
          if (rv == SECSuccess) {
            tempCert.forget(); // ownership traferred to validationChain
          } else {
            CERT_DestroyCertList(*validationChain);
            *validationChain = nullptr;
          }
        }
      }
    } else {
      // Validation was a fail, clean up if needed
      if (cvout[validationChainLocation].value.pointer.chain) {
        CERT_DestroyCertList(cvout[validationChainLocation].value.pointer.chain);
      }
    }
  }

  return rv;
#endif
}