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

📄 pkixcertpathval.c

📁 PGP8.0源码 请认真阅读您的文件包然后写出其具体功能
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Copyright (C) 2002 PGP Corporation
   All Rights Reserved.

   Author: Michael_Elkins@nai.com
   Last Edit: March 22, 1999 */

/* This file contains code implementing the "Basic Path Validitation"
   algorithm described in section 6.1 of RFC2459 */

#include "cms.h"

#define TC_F_PERMIT         0x010000

/*****
 *
 * tc_find_crl
 *
 * Inputs:
 *	issuer
 *		Certificate for issuer of crl.  this is a pointer to the
 *		certificate, and not just the DN since the cert is required
 *		to verify the CRL.
 *
 *	ctx
 *		CMS context structure.
 *
 * Outputs:
 *	crl
 *		Pointer to requested CRL.  NOTE: this is a pointer to the
 *		in-store copy of the CRL and the application SHOULD NOT free
 *		it.
 *
 * Returns:
 *	0	success
 *	<0	failure
 */

static int
tc_find_crl (TC_CertificateList **crl, /* OUT */
	     TC_CERT *issuer, /* IN */
	     TC_CONTEXT *ctx) /* IN */
{
    int status=TC_E_NOTFOUND; /*crl not found*/
    TC_CertificateList *list;
    TC_LIST *entry;

    if(!crl||!issuer||!ctx)
	return TC_E_INVARGS;

    *crl=NULL;/*clear input*/

    for (entry=ctx->crl; entry; entry=entry->next)
    {
	list = (TC_CertificateList *) entry->data;
	if (tc_compare_dname (&list->tbsCertList.issuer,
			      &issuer->tbsCertificate->issuer,
			      ctx))
	{
	    status=0;
	    *crl=list;
	    break;
	}
    }
    return status;
} /* tc_find_crl */

/*****
 *
 * tc_validate_crl
 *
 * Performs integrity check and PKIX compliance test on specified CRL.
 *
 * Inputs:
 *	crl
 *		CRL to validate.
 *
 *	issuer
 *		Certificate of CRL issuer.
 *
 *	flags
 *		TC_F_PKIX
 *			Turn on pedantic checks required by RFC2459 for CRLs.
 *
 *	ctx
 *		CMS context structure.
 *
 * Returns:
 *	0	success
 *	<0	failure
 */

static int
tc_validate_crl (TC_CertificateList *crl,
		 TC_CERT *issuer,
		 int flags,
		 TC_CONTEXT *ctx)
{
    unsigned char *blob;
    size_t blobsize;
    TC_Extension *ext;
    int status=0, n;

    /* verify signature algorithms are the same on the inside and outside of
       signed block */
    if (tc_compare_block (&crl->signatureAlgorithm.algorithm,
			  &crl->tbsCertList.signature.algorithm) != 1)
	return TC_E_INVALIDCRL; /* signature OIDs do not match */

    if (flags & TC_F_PKIX)
    {
	/* verify version 2 CRL */
	if (!crl->tbsCertList.version ||
	    PKIGetIntVal (ctx->certasnctx, crl->tbsCertList.version, &status) != 1)
	    return TC_E_NOTV2CRL;
	if (status)
	    return (compiler2tc_error (status));

	/* TODO: RFC2459 Section 5.1.2.4 states that for times <2050A.D. CAs
	   MUST use UTCTime, otherwise use GeneralizedTime for >2050A.D.

	   CMS uses `time_t' which on most systems overflows in the year
	   2038. */

	/* verify the existence of the `nextUpdate' field */
	if(!crl->tbsCertList.nextUpdate)
	    return TC_E_MISSINGNEXTUPDATE;

	/* ----- check for mandatory crl extensions ----- */
	status=tc_find_extension(&ext,
				 crl->tbsCertList.crlExtensions,
				 PKIid_ce_authorityKeyIdentifier_OID,
				 PKIid_ce_authorityKeyIdentifier_OID_LEN,
				 ctx);
	if(status)
	    return TC_E_MISSINGAUTHKEYIDEXT;

	status=tc_find_extension(&ext,
				 crl->tbsCertList.crlExtensions,
				 PKIid_ce_cRLNumber_OID,
				 PKIid_ce_cRLNumber_OID_LEN,
				 ctx);
	if(status)
	    return TC_E_MISSINGCRLNUMBEREXT;
    }

    /* verify signature */
    blobsize=PKISizeofTBSCertList(ctx->certasnctx,&crl->tbsCertList,PKITRUE);
    blob=TC_Alloc(ctx->memMgr,blobsize);
    if(!blob)
	return TC_E_NOMEMORY;
    PKIPackTBSCertList(ctx->certasnctx,blob,blobsize,&crl->tbsCertList,&status);
    if(!status)
    {
	status = ctx->verify(blob,
			     blobsize,
			     crl->signatureAlgorithm.algorithm.val,
			     crl->signatureAlgorithm.algorithm.len,
			     crl->signatureAlgorithm.parameters ? crl->signatureAlgorithm.parameters->val : NULL,
			     crl->signatureAlgorithm.parameters ? crl->signatureAlgorithm.parameters->len : 0,
			     crl->signature.val,
			     crl->signature.len,
			     issuer->tbsCertificate->subjectPublicKeyInfo.subjectPublicKey.val,
			     issuer->tbsCertificate->subjectPublicKeyInfo.subjectPublicKey.len,
			     issuer,
			     ctx->verfuncdata,
			     ctx);

    }

    /* process crl extensions */
    if (status == 0 && crl->tbsCertList.crlExtensions)
    {
	status=tc_process_extensions(crl->tbsCertList.crlExtensions,
				     (void*) crl,
				     ctx);
    }

    /* process CRL entry extensions */
    if (status == 0 && crl->tbsCertList.revokedCertificates)
    {
	for (n=0; n < crl->tbsCertList.revokedCertificates->n; n++)
	{
	    status = tc_process_extensions (crl->tbsCertList.revokedCertificates->elt[n]->crlEntryExtensions,
					    (void *) crl,
					    ctx);
	    if (status)
		break;
	}
    }

    TC_Free(ctx->memMgr,blob);
    return status;
} /* tc_validate_crl */

/*****
 *
 * tc_cert_not_revoked
 *
 * Checks CRL for presence of specified certificate.  This function assumes
 * the caller has already checked the CRL using tc_validate_crl().
 *
 * Inputs:
 *	cert
 *		certificate to validate
 *	crl
 *		revocation list to check
 *	when
 *		time at which to check for revocation
 *	flags
 *		should be 0 (none specified)
 *	ctx
 *		CMS context structure
 *
 * Returns:
 *	0	success (certificate is not revoked)
 *	<0	error or certificate is revoked
 */

static int
tc_cert_not_revoked (TC_CERT *cert,
		     TC_CertificateList *crl,
		     time_t when,
		     int flags,
		     TC_CONTEXT *ctx)
{
    int i,status;
    time_t revoked;

    (void) flags;
    /* verify that the certificate specified was issued by the issuer of the
       CRL */
    status = tc_compare_dname (&cert->tbsCertificate->issuer,
			       &crl->tbsCertList.issuer,
			       ctx);
    if (status!=1)
	return TC_E_WRONGCRL;

    /* search the revoked certs list for the named cert */
    if (crl->tbsCertList.revokedCertificates)
    {
	for (i=0; i<crl->tbsCertList.revokedCertificates->n; i++)
	{
	    status = tc_compare_serial (&cert->tbsCertificate->serialNumber,
					&crl->tbsCertList.revokedCertificates->elt[i]->userCertificate);
	    if (status==1)
	    {
		revoked = tc_get_choiceoftime (&crl->tbsCertList.revokedCertificates->elt[i]->revocationDate,
					       ctx);
		return ((when>=revoked) ? TC_E_CERTREVOKED : 0);
	    }
	}
    }

    return 0;
} /* tc_cert_not_revoked */

/*****
 *
 * tc_check_rfc822name_constraint
 *
 * Returns:
 *	1	constraint matches
 *	0	constraint does not match
 */

static int
tc_check_rfc822name_constraint (PKIIA5String *n, PKIIA5String *rfc)
{
    if(n->len < rfc->len)
	return 0;
    return((memcmp(rfc->val,n->val + n->len - rfc->len, rfc->len) == 0));
} /* tc_check_rfc822name_constraint */

/* RFC2459: DNS name restrictions are expressed as foo.bar.com.  Any subdomain
   satisfies the name constraint.  For example, www.foo.bar.com would satisfy
   the constraint but bigfoo.bar.com would not. */
static int tc_check_dnsname_constraint (PKIIA5String *n, PKIIA5String *c)
{
    if(n->len < c->len)
	return 0;
    if (memcmp(n->val+n->len-c->len,c->val,c->len))
	return 0;
    if(n->val==c->val)
	return 1;/*exact match*/
    /* ensure this is a valid subdomain, and doesn't match part of another
       name */
    return ((*(n->val+n->len-c->len-1) == '.'));
} /* tc_check_dnsname_constraint */

static int tc_check_uri_constraint (PKIIA5String *url, PKIIA5String *c)
{
    unsigned char *p, *e;
    size_t l;

    p=url->val;
    while ((size_t)(p - url->val) < url->len - 3 &&
	   !(*p == ':' && *(p+1)=='/' && *(p+2)=='/'))
	p++;
    if(*p!=':')
	return TC_E_INVALIDURI;
    p+=3;/*skip over the :// */

    /* now find the end of the hostname */
    e=p;
    while((size_t)(e - url->val) < url->len && *e != '/' && *e != ':')
	e++;

    l=e-p;/*length of hostname */

    if(l<c->len)
	return 0;

    if(memcmp(p+l-c->len,c->val,c->len))
	return 0;

    if(l==c->len)
	return 1;/*exact match*/

    if(*c->val!='.' && *(p+l-c->len-1)!='.')
	return 0; /* not a subdomain */

    return 1;/*valid subdomain */
} /* tc_check_uri_constraint */

static int
tc_check_ipaddress_constraint (PKIOCTET_STRING *ip, PKIOCTET_STRING *c)
{
    size_t i;

    if(ip->len * 2 != c->len)
	return TC_E_INVALIDIPCONSTRAINT;
    for(i=0;i<ip->len;i++)
    {
	if ((ip->val[i] & c->val[i+ip->len]) != (c->val[i] & c->val[i+ip->len]))
	    return 0;
    }
    return 1;
} /* tc_check_ipaddress_constraint */

static int tc_check_name_constraint (PKIGeneralName *name,
				     PKIGeneralSubtree *constraint,
				     TC_CONTEXT *ctx)
{
    int status=0;

    (void)ctx;

    /*NOTE: otherName, ediPartyName and registeredID are not required
      to be handled for PKIX compliance */

    /* TODO: for rfc822Name we also need to check the DN for the EmailAddress
       attribute if the subjectAltName is missing */
    if(name->CHOICE_field_type != constraint->base.CHOICE_field_type)
	return TC_E_WRONGNAMETYPE;

    switch(constraint->base.CHOICE_field_type)
    {
	case 0xa1: /* rfc822Name */
	    status=tc_check_rfc822name_constraint(name->data,
						  constraint->base.data);
	    break;
	case 0xa2: /* dNSName */
	    status=tc_check_dnsname_constraint(name->data,
					       constraint->base.data);
	    break;
	case 0xa3: /* x400Address */
	    status=TC_E_NAMETYPEUNSUPPORTED;/* not supported */
	    break;
	case 0xa4: /* directoryName */
	    /* TODO */
	    break;
	case 0xa6: /* URI */
	    status=tc_check_uri_constraint(name->data,
					   constraint->base.data);
	    break;
	case 0xa7: /* iPAddress */
	    status=tc_check_ipaddress_constraint(name->data,
						 constraint->base.data);
	    break;
    }
    return status;
} /* tc_check_name_constraint */

/*****
 *
 * tc_check_name_constraint
 *
 * Checks whether the given name matches the specified constraint pattern.
 *
 * Input:
 *	name
 *		name to check
 *	constraint
 *		tree of matching names
 *	flags
 *		TC_F_PERMIT
 *			all matched name types MUST match the constraint
 *	ctx
 *		CMS context structure
 *
 * Returns:
 *	0	name is consistent with constraint
 *	<0	error
 */

static int tc_check_name_constraints (PKIGeneralName *name,
				      PKIGeneralSubtrees *constraint,
				      int flags,
				      TC_CONTEXT *ctx)
{
    int n,status=0;

    for(n=0;n<constraint->n;n++)
    {
	status=tc_check_name_constraint(name,constraint->elt[n],ctx);
	if(status==0)
	{
	    /* name type exists, constraint does not match */
	    if(flags & TC_F_PERMIT)
		return TC_E_CONSTRAINTFAIL;
	}
	else if (status==1)
	{
	    /* name type exists, constraint matches */
	    if(!(flags & TC_F_PERMIT))
		return TC_E_CONSTRAINTFAIL;
	}
    }
    return 0;
} /* tc_check_name_constraints */

static int tc_do_name_constraints (PKIGeneralName *sdn,
				   PKISubjectAltName *san,
				   PKIGeneralSubtrees *tree,
				   int flags,
				   TC_CONTEXT *ctx)
{
    int j, status;

    /* first check subject name */
    status=tc_check_name_constraints(sdn, tree, flags, ctx);

⌨️ 快捷键说明

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