⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pkixcertpathval.c

📁 可以实现对邮件的加密解密以及签名
💻 C
📖 第 1 页 / 共 3 页
字号:
    int bits=0, status;
    size_t i;

    status = tc_find_extension (&ext,
				cert->tbsCertificate->extensions,
				PKIid_ce_keyUsage_OID,
				PKIid_ce_keyUsage_OID_LEN,
				ctx);
    if (status)
	return 0;

    PKIUnpackKeyUsage (ctx->certasnctx,
		       &ku,
		       ext->extnValue.val,
		       ext->extnValue.len,
		       &status);
    if (status)
	return (compiler2tc_error (status));

    for (i=0;i<ku->len;i++)
    {
	bits <<= 8;
	bits |= ku->val[i];
    }
    bits >>= ku->nuub;

    status = (bits & PKIKeyUsage_keyCertSign) ? 0 : TC_E_NOTSIGNINGKEY;

    PKIFreeKeyUsage (ctx->certasnctx, ku);

    return status;
}

/*****
 *
 * tc_validate_path
 *
 * Inputs:
 *	cert
 *		end entity certificate of path to validate
 *
 *	when
 *		time at which validity is being checked for.  According to
 *		RFC2459, this can be "the current date/time, or some point in
 *		the past."  Future validity can not be determined since the
 *		certificate could be revoked at any time.
 *
 *	policy
 *		acceptable certificate policies for this validation (not
 *		implemented)
 *
 *  flags
 *		TC_F_PKIX
 *			enables stricter PKIX certificate checking
 *
 *	ctx
 *		CMS context structure, which should contain the necessary
 *		certificates and CRLs required for validation of the path.
 *
 * Returns:
 *	0	success
 *	<0	failure
 */

int tc_validate_path (TC_CERT *eecert,
		      PKICertificatePolicies *initialPolicies,
		      time_t when,
		      int flags,
		      TC_CONTEXT *ctx)
{
    /* STATE VARIABLES */

    PKICertificatePolicies *acceptablePolicies=NULL;
    PKIGeneralSubtrees *constrainedSubtrees=NULL;
    PKIGeneralSubtrees *excludedSubtrees=NULL;
    int explicitPolicy;
    int policyMapping;
    int maxPathLen; /*basicConstraints*/

    /* local variables */

    TC_CERT *cert;
    int i,j,status=0, chainsize=0;
    time_t notBefore,notAfter;
    TC_CertificateList *crl;
    TC_CERT **chain=NULL;
    PKIGeneralName dummy;
    PKISubjectAltName *san=NULL;

    /* PKIX path validation begins with the CA certificate, so we must first
       locate it in the store. */

    TC_Realloc (ctx->memMgr,(void**)&chain,sizeof(TC_CERT *)*(chainsize+1));
    chain[chainsize++] = eecert;

    while (!tc_is_self_signed (chain[chainsize-1], ctx))
    {
	status = tc_find_issuer(&cert,chain[chainsize-1],ctx);
	if (status)
	    goto error;
	TC_Realloc (ctx->memMgr,(void**)&chain,sizeof(TC_CERT *)*(chainsize+1));
	chain[chainsize++]=cert;
    }

    explicitPolicy = chainsize;
    policyMapping = chainsize;
    maxPathLen = chainsize;

    /* we need to process the chain from the root (CA) certificate down to the
       end entity certificate in question.  this is necessary since the CA
       certificate(s) may have certain restrictions which need to be processed
       before end entity validity can be determined. */
    tc_reverse_chain (chain, chainsize);

    /* loop through all certificate in the chain, starting with the CA cert */
    for (i = 0; i < chainsize; i++)
    {
	/* if the maximum number of certificates in the change has been
	   exceeded, the certificate is not valid */
	if (maxPathLen == 0)
	{
	    status = TC_E_PATHCONSTRAINT;
	    goto error;
	}
	maxPathLen--;

	/* ----- verify basic certificate information ----- */

	/* check version number and format of message */
	if (!chain[i]->tbsCertificate->version)
	{
	    /* version 1 */
	    if (chain[i]->tbsCertificate->subjectUniqueID ||
	        chain[i]->tbsCertificate->issuerUniqueID ||
		chain[i]->tbsCertificate->extensions)
	    {
		/* version 1 x.509 certs should not have these fields */
		status = TC_E_NOTV1CERT;
		goto error;
	    }
	}
	else
	{
	    int version = PKIGetIntVal(ctx->certasnctx,
				       chain[i]->tbsCertificate->version,
				       &status);

	    if (version == 0)
	    {
		/* if we have a version 1 cert, the version field should be
		   absent */
		status = TC_E_EXPLICITV1;
		goto error;
	    }
	    else if (version == 1) /* v2 */
	    {
		if ((!chain[i]->tbsCertificate->subjectUniqueID &&
		    !chain[i]->tbsCertificate->issuerUniqueID) ||
		    chain[i]->tbsCertificate->extensions)
		{
		    status = TC_E_NOTV2CERT;
		    goto error;
		}
	    }
	    else if (version == 2) /* v3 */
	    {
		/* v3 certs should always have at least one extension */
		if (!chain[i]->tbsCertificate->extensions)
		{
		    status = TC_E_NOTV3CERT;
		    goto error;
		}
	    }
	}

	/* verify that the inner and outer signature algorithms OIDs are
	   the same */
	if (!tc_compare_block (&chain[i]->tbsCertificate->signature.algorithm,
			       &chain[i]->cert->signatureAlgorithm.algorithm))
	{
	    /* OIDs differ */
	    status = TC_E_SIGALGMISMATCH;
	    goto error;
	}

	/*if we are processing a self-signed cert, it is its own issuer*/
	cert = (i == 0) ? chain[0] : chain[i-1];

	/* (a) (1) verify the signature on the subject certificate*/
	status = ctx->verify(chain[i]->cert->tbsCertificate.val,
			     chain[i]->cert->tbsCertificate.len,
			     chain[i]->cert->signatureAlgorithm.algorithm.val,
			     chain[i]->cert->signatureAlgorithm.algorithm.len,
			     chain[i]->cert->signatureAlgorithm.parameters ? chain[i]->cert->signatureAlgorithm.parameters->val : NULL,
			     chain[i]->cert->signatureAlgorithm.parameters ? chain[i]->cert->signatureAlgorithm.parameters->len : 0,
			     chain[i]->cert->signature.val,
			     chain[i]->cert->signature.len,
			     cert->tbsCertificate->subjectPublicKeyInfo.subjectPublicKey.val,
			     cert->tbsCertificate->subjectPublicKeyInfo.subjectPublicKey.len,
			     cert,
			     ctx->verfuncdata,
			     ctx);

	if (status)
	    goto error;

	/* (a) (2) verify the validity period includes `when'*/
	notBefore=tc_get_choiceoftime(&chain[i]->tbsCertificate->validity.notBefore,ctx);
	notAfter=tc_get_choiceoftime(&chain[i]->tbsCertificate->validity.notAfter,ctx);
	if (when > time(0) || when < notBefore || when > notAfter)
	{
	    /* outside of validity period */
	    status=TC_E_INVDATE;
	    goto error;
	}

	/* locate the signer's crl */
	status = tc_find_crl (&crl, cert, ctx);
	if (status == 0)
	{
	    /*validate the CRL*/
	    status = tc_validate_crl (crl,cert,flags,ctx);
	    if (status)
		goto error;

	    /* (a) (3) verify certificate was not revoked at time `when'*/
	    status = tc_cert_not_revoked (chain[i],crl,when,0,ctx);
	    if (status)
		goto error;
	}
	else if (status != TC_E_NOTFOUND)
	    goto error;

	/* (a) (4) verify subject and issuer names chain correctly.

	   this is implicitly done above in bulding the the array of
	   certificates to validate. */

	/* locate the subjectAltName extension for following checks */
	if (cert->tbsCertificate->extensions)
	{
	    PKIExtension *ext;

	    status=tc_find_extension(&ext,
				     cert->tbsCertificate->extensions,
				     PKIid_ce_subjectAltName_OID,
				     PKIid_ce_subjectAltName_OID_LEN,
				     ctx);
	    if (status == 0)
	    {
		PKIUnpackSubjectAltName(ctx->certasnctx,
					&san,
					ext->extnValue.val,
					ext->extnValue.len,
					&status);
		if (status)
		{
		    status=compiler2tc_error(status);
		    goto error;
		}
	    }
	}
	else if (flags & TC_F_PKIX)
	{
	    /* if we are doing pedantic PKIX checking, the fact that there are
	       no certificates extensions is an error since all certificates
	       are required to have at least the AuthorityKeyIdentifier
	       extension */
	    goto error;
	}
	else
	    san = NULL; /* subjectAltName */

	/* create dummy general name with the DN in it */
	memset (&dummy, 0, sizeof (dummy));
	dummy.CHOICE_field_type = 0xa4; /* directoryName */
	dummy.data = (void*)&chain[i]->tbsCertificate->subject;

	/* (b) verify that the subject name and subjectAltName extension
	   (critical or not) is consistent with the constrained subtrees
	   state variable. */
	if (constrainedSubtrees)
	{
	    status=tc_do_name_constraints(&dummy,
					  san,
					  constrainedSubtrees,
					  TC_F_PERMIT,
					  ctx);
	    if(status)
		goto error;
	}

	/* (c) verify that the subject name and subjectAltName extension
	   (critical or not) is consistent with the excluded subtrees
	   state variables */

	if (excludedSubtrees) {
	    status = tc_do_name_constraints (&dummy,
					     san,
					     excludedSubtrees,
					     0,
					     ctx);
	    if (status)
		goto error;
	}

	/* (d) verify that policy information is consistent with the initial
	   policy set. */

	/* (d) (1) */
	if (explicitPolicy <= i) {
	    status = tc_verify_policy (initialPolicies, chain[i], ctx);
	    if (status)
		goto error;
	}

	/* (d) (2) ensure policy is not mapped */
	if (policyMapping <= i) {
	    PKIExtension *ext;

	    status = tc_find_extension (&ext,
					chain[i]->tbsCertificate->extensions,
					PKIid_ce_policyMappings_OID,
					PKIid_ce_policyMappings_OID_LEN,
					ctx);
	    if (status == 0) {
		status = TC_E_POLICYMAPPED;
		goto error;
	    }
	}

	/* (e) verify that the policy information is consistent with the
	   acceptable policy set: */

	/* (e) (1) if certificate policies extension is marked critical,
	   the intersection of the policies extension and the acceptable
	   policy set shall be non-null */

	/* (e) (2) the acceptable policy set is assigned the resulting
	   intersection as its new value. */

	status = tc_policy_intersect (chain[i], &acceptablePolicies, ctx);
	if (status)
	    goto error;

	/* (g) verify that the intersection of the acceptable policy set
	   and initial policy set is non-null */

	if (initialPolicies && acceptablePolicies) {
	    status = TC_E_POLICYMISMATCH;
	    for ( j = 0 ; j < initialPolicies->n ; j++ ) {
		if (tc_find_policy (&initialPolicies->elt[j]->policyIdentifier,
				    acceptablePolicies) >= 0) {
		    status = 0;
		    break;
		}
	    }
	    if (status)
		goto error;
	}

	/* (h) recognize and process any other critical extensions present
	   in the certificate */

	status = tc_process_extensions (chain[i]->tbsCertificate->extensions,
					(void *) chain[i],
					ctx);
	if (status)
	    goto error;

	/* the following checks only apply to CA certificates */
	if (i < chainsize - 1) {
	    /* (i) verify that the certificate is a CA certificate
	       (as specified in a basicConstraints extension or as verified
	       out-of-band). */

	    status = tc_process_basic_constraints (chain[i], &maxPathLen, ctx);
	    if (status)
		goto error;

	    /* (j) if permittedSubtrees is present in the certificate, set
	       the constrained subtrees state variable to the intersection
	       of its previous value and the value indicated in the
	       extension field */

	    /* (k) if excludedSubtrees is present in the certificate, set
	       the excluded subtrees variable stat variable to the union of its
	       previous value and the value indicated in the extension field. */

	    status = tc_name_constraints_intersect (cert,
						    &constrainedSubtrees,
						    &excludedSubtrees,
						    ctx);
	    if (status)
		goto error;

	    /* (l) if a policy constraints extension is included in the
	       certificate, modify the explicit policy and policy mapping
	       state variables as follows:

	       (l) (1) if requireExplicitPolicy is present and has value r,
	       the explicit policy mapping state variable is set to the
	       minimum of its current value and the sum of r and i (the
	       current certificate in the sequence).

	       (l) (2) if inhibitPolicyMapping is present and has value q,
	       the policy mapping state variable is set to the minimum of
	       its current value and the sum of q and i (the current
	       certificate in the sequence). */

	    status = tc_process_policy_constraints (cert,
						    i,
						    &explicitPolicy,
						    &policyMapping,
						    ctx);
	    if (status)
		goto error;

	    /* (m) if a key usage extension is marked critical, ensure the
	       keyCertSign bit is set */

	    status = tc_process_key_usage (cert, ctx);
	    if (status)
		goto error;
	}

	/* clean up */
	PKIFreeSubjectAltName(ctx->certasnctx,san);
	san=NULL;
    }

error:
    if(chain)
	TC_Free(ctx->memMgr,chain);
    if(san)
	PKIFreeSubjectAltName(ctx->certasnctx,san);
    return status;
} /* tc_validate_path */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -