📄 pkixcertpathval.c
字号:
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 + -