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

📄 pkixcheck.c

📁 可以实现对邮件的加密解密以及签名
💻 C
📖 第 1 页 / 共 2 页
字号:
/****
 *
 * tc_CertCheckPKIXCompliance
 *
 * Check the provided certificate for PKIX part 1 compliance.  The paragraph
 * numbers from the spec. where the requirements are located are included
 * in the comments.  This routine checks what it can, but it can't check
 * everything since it only has the certificate information in isolation.  For
 * instance, it can't check that the serial number is unique for the issuing
 * CA.
 *
 * The routine will return the first error found.  It goes through all the
 * checks it can and if you would like all the possible errors, you can provide
 * pointers for numErrors and errorList to receive an array of all the errors
 * found.  You are responsible for deallocating the memory in errorList in
 * this case.
 *
 * If there is a problem in the processing itself (eg., memory allocation
 * problem, then the routine will set  errorList and numErrors to NULL
 * and return an error appropriate to the problem (eg., TC_E_NOMEMORY).
 *
 * Note: this call does not assume the cert was created with tc_create_cert()
 * since the caller could have changed some values on their own.  It does
 * assume that a newly created certificate structure is being checked so
 * it will return errors for items related to newly created certs (eg.,
 * issuer unique identifier should not be present )
 *
 *****/

int tc_CertCheckPKIXCompliance(
    const TC_CERT    *cert,
    TC_CertType      certType,
    int              **errorList,
    int              *numErrors,
    TC_CONTEXT       *ctx)
{
    int localErrors[300];
    int localNumErrors;

    PKIAlgorithmIdentifier  *sigAlg;
    TC_TBSCertificate *tbsCert;
    PKIRDNSequence *rdnSeq;
    PKIAlgorithmIdentifier *keyAlg;
    int ver;
    int error = 0;
    int i;
    
    if (cert == NULL || ctx == NULL)
	return TC_E_INVARGS;

    if (errorList != NULL)
	*errorList = NULL;
    if (numErrors != NULL)
	*numErrors = 0;
    localErrors[0] = 0;
    localNumErrors = 0;

    tbsCert = cert->tbsCertificate;

    /* sigAlg field same as signature field in tbsCert; 4.1.1.2 & 4.1.2.3 */
    sigAlg = &cert->cert->signatureAlgorithm;
    if (tbsCert->signature.algorithm.len != sigAlg->algorithm.len ||
	memcmp(tbsCert->signature.algorithm.val,
	       sigAlg->algorithm.val, sigAlg->algorithm.len) != 0)
    {
	localErrors[localNumErrors] = TC_E_SigAlgSignatureMismatch;
	localNumErrors++;
    }

    /* version value omitted when its v1, version value is v2 when 
       UniqueIdentifier is present, version is v3 when extensions
       present; 4.1.2.1 */
    if (tbsCert->version != NULL)
    {
	ver = PKIGetIntVal(ctx->certasnctx, tbsCert->version, &error);
	if (tbsCert->extensions != NULL &&
	    ver != TC_X509_VERSION_3)
	{
	    localErrors[localNumErrors] = TC_E_VersionShouldBe3;
	    localNumErrors++;
	}
	else if ( (tbsCert->issuerUniqueID != NULL ||
		   tbsCert->subjectUniqueID != NULL) &&
		  ver != TC_X509_VERSION_2)
	{
	    localErrors[localNumErrors]  = TC_E_VersionShouldBe2;
	    localNumErrors++;
	}
	else
	{
	    localErrors[localNumErrors] = TC_E_VersionShouldBeNULL;
	    localNumErrors++;
	}
    }
    else /* NULL version, so its v1 */
    {
	if (tbsCert->extensions != NULL)
	{
	    localErrors[localNumErrors] = TC_E_VersionShouldBe3;
	    localNumErrors++;
	}
	else if (tbsCert->issuerUniqueID != NULL ||
		 tbsCert->subjectUniqueID != NULL )
	{
	    localErrors[localNumErrors] = TC_E_VersionShouldBe2;
	    localNumErrors++;
	}
    }

    /* issuer field is not empty, this assumes the Name CHOICE is
       the RDNSequence type; 4.1.2.4 */
    rdnSeq = (PKIRDNSequence *)tbsCert->issuer.data;
    if (rdnSeq->n <= 0)
    {
	localErrors[localNumErrors] = TC_E_EmptyIssuerName;
	localNumErrors++;
    }

    /* Dname checks */
    /* call CheckDname() with subject */

    /* validity is UTCTime until 2049, assuming current size of time_t
       is 4 bytes, we can reliably check for date until 2038, so fail
       then with different error.  Hopefully this will cause a look
       at the code so it can be updated as needed. See comments in
       tc_encode_utctime() for more details like where the numbers
       below came from. 4.1.2.5 */
    if (time(NULL) > (2147483647L - (31536000/2)) )
    {
	localErrors[localNumErrors] = TC_E_CantHandleCurrentTimeValue;
	localNumErrors++;
    }
    else
    {
	if (tbsCert->validity.notBefore.CHOICE_field_type != 
	                                               PKIID_UTCTime ||
	    tbsCert->validity.notAfter.CHOICE_field_type != 
                                                       PKIID_UTCTime )
	{
	    localErrors[localNumErrors] = TC_E_ValidityNotUTCTime;
	    localNumErrors++;
	}
    }    

    /* CA cert has non-empty subject field; 4.1.2.6 */
    if (certType == TC_RootCertAuthority ||
	certType == TC_CertificateAuthority)
    {

	rdnSeq = (PKIRDNSequence *)tbsCert->subject.data;
	if (rdnSeq->n <= 0)
	{
	    localErrors[localNumErrors] = TC_E_EmptyIssuerName;
	    localNumErrors++;
	}
    }

    /* root cert has same issuer/subject fields; 4.1.2.6 */
    if (certType == TC_RootCertAuthority)
    {
	if (tc_compare_dname(&tbsCert->issuer, &tbsCert->subject,
			     ctx) != 1)
	{
	    localErrors[localNumErrors] = TC_E_IssuerSubjectNotSameInRootCert;
	    localNumErrors++;
	}
    }

    /* new certs should not have subject/issuer unique identifier; 4.1.2.7 */
    if (tbsCert->issuerUniqueID != NULL)
    {
	localErrors[localNumErrors] = TC_E_IssuerUniqueIDPresent;
	localNumErrors++;
    }
    if (tbsCert->subjectUniqueID != NULL)
    {
	localErrors[localNumErrors] = TC_E_SubjectUniqueIDPresent;
	localNumErrors++;
    }

    /* Extension checks */
    CheckExtensions(tbsCert, certType, localErrors, &localNumErrors, ctx);

    /* if its RSA, parameters must be present and NULL in the
       AlgorithmIdentifier field, need to check each field; 7.2.1 */

    /* the signature field in TBSCertificate */
    sigAlg = &tbsCert->signature;
    if ( GetAlgorithm(sigAlg->algorithm) == ALG_RSA)
    {
	if (sigAlg->parameters == NULL)
	{
	    localErrors[localNumErrors] = TC_E_RSAParametersMissing;
	    localNumErrors++;
	}
	else if (sigAlg->parameters->len < 2 ||
		 sigAlg->parameters->val[0] != 0x50)
	{
	    localErrors[localNumErrors] = TC_E_RSAParametersNotASN1NULL;
	    localNumErrors++;
	}
    }

    /* the subjectPublicKeyInfo field in TBSCertificate */
    keyAlg = &tbsCert->subjectPublicKeyInfo.algorithm;
    if ( GetAlgorithm(keyAlg->algorithm) == ALG_RSA)
    {
	if (keyAlg->parameters == NULL)
	{
	    localErrors[localNumErrors] = TC_E_RSAParametersMissing;
	    localNumErrors++;
	}
	else if (keyAlg->parameters->len < 2 ||
		 keyAlg->parameters->val[0] != 0x50)
	{
	    localErrors[localNumErrors] = TC_E_RSAParametersNotASN1NULL;
	    localNumErrors++;
	}
    }

    /* the signatureAlgorithm field in Certificate */
    sigAlg = &cert->cert->signatureAlgorithm;
    if ( GetAlgorithm(sigAlg->algorithm) == ALG_RSA)
    {
	if (sigAlg->parameters == NULL)
	{
	    localErrors[localNumErrors] = TC_E_RSAParametersMissing;
	    localNumErrors++;
	}
	else if (sigAlg->parameters->len < 2 ||
		 sigAlg->parameters->val[0] != 0x50)
	{
	    localErrors[localNumErrors] = TC_E_RSAParametersNotASN1NULL;
	    localNumErrors++;
	}
    }

    /* if its DSA, parameters field absent in AlgorithmIdentifier field
       for the signature field in TBSCertificate and the signatureAlgorithm
       field in Certificate; 7.2.2 */
    sigAlg = &tbsCert->signature;
    if ( GetAlgorithm(sigAlg->algorithm) == ALG_DSA)
    {
	if (sigAlg->parameters != NULL)
	{
	    localErrors[localNumErrors] = TC_E_DSAParametersArePresent;
	    localNumErrors++;
	}
    }

    sigAlg = &cert->cert->signatureAlgorithm;
    if ( GetAlgorithm(sigAlg->algorithm) == ALG_DSA)
    {
	if (sigAlg->parameters != NULL)
	{
	    localErrors[localNumErrors] = TC_E_DSAParametersArePresent;
	    localNumErrors++;
	}
    }

    /* create the error list to return if requested */
    if (errorList != NULL && numErrors != NULL)
    {
	*errorList = (int *)TC_Alloc(ctx->memMgr, sizeof(int) * localNumErrors);
	if (errorList == NULL)
	    return TC_E_NOMEMORY;

	for (i = 0; i < localNumErrors; i++)
	    (*errorList)[i] = localErrors[i];
	*numErrors = localNumErrors;
    }

    return localErrors[0]; /* return the first error found */

} /* tc_CertCheckPKIXCompliance */


/****
 *
 * tc_CRLCheckPKIXCompliance
 *
 *****/
int tc_CRLCheckPKIXCompliance(
    const TC_CertificateList *crl,
    TC_CRLType  crlType,
    TC_CONTEXT *ctx)
{
    int status = 0;

    if (crl == NULL || ctx == NULL)
	return TC_E_INVARGS;

    /* version is v2 */

    /* issuer field is not empty, this assumes the Name CHOICE is
       the RDNSequence type; 5.1.3.2 */

    /* include nextUpdate field */

    /* include CRL number extension */

    /* include authority key identifier field */

    /* signatureAlgorithm field same as signature field in tbsCertList */

    /* issuer name is present */

    /* thisUpdate and nextUpdate are UTCTime until 2049 */

    /* nextUpdate later than thisUpdate */

    /* issuing distribution point ext is critical if there */

    /* reason code ext is not critical */

    /* don't use 'unspecified' in reason code ext. */

    /* hold instruction code is not critical */

    /* hold instruction codes recognized are (see para 5.3.2) */

    /* invalidity data ext is not critical */

    /* cert issuer CRL entry ext. is critical */

    /* if its RSA, parameters must be present and NULL */

    /* if its DSA, parameters field abscent in AlgorithmIdentifier field */

    return status;

} /* tc_CRLCheckPKIXCompliance */

⌨️ 快捷键说明

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