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

📄 certsign.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 4 页
字号:

static int checkSelfSignedCert( CERT_INFO *certInfoPtr, 
								const int formatInfo )
	{
	CRYPT_CONTEXT iCryptContext;
	CERT_INFO *issuerCertInfoPtr;
	int status;

	/* Since there's no signer cert provided it has to be either explicitly 
	   self-signed or signed by a trusted cert */
	if( certInfoPtr->flags & CERT_FLAG_SELFSIGNED )
		{
		iCryptContext = certInfoPtr->iPubkeyContext;
		issuerCertInfoPtr = certInfoPtr;
		}
	else
		{
		CRYPT_CERTIFICATE iCryptCert = certInfoPtr->objectHandle;

		/* If it's a certificate, it may be implicitly trusted */
		if( ( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
			  certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT ) && \
			cryptStatusOK( \
				krnlSendMessage( certInfoPtr->ownerHandle, 
								 IMESSAGE_SETATTRIBUTE, &iCryptCert, 
								 CRYPT_IATTRIBUTE_CERT_CHECKTRUST ) ) )
			/* The cert is implicitly trusted, we're done */
			return( CRYPT_OK );

		/* If it's not self-signed, it has to be signed by a trusted cert */
		status = krnlSendMessage( certInfoPtr->ownerHandle, 
								  IMESSAGE_SETATTRIBUTE, &iCryptCert, 
								  CRYPT_IATTRIBUTE_CERT_TRUSTEDISSUER );
		if( cryptStatusError( status ) )
			/* There's no trusted signer present, indicate that we need
			   something to check the cert with */
			return( CRYPT_ARGERROR_VALUE );
		status = krnlAcquireObject( iCryptCert, OBJECT_TYPE_CERTIFICATE, 
									( void ** ) &issuerCertInfoPtr, 
									CRYPT_ERROR_SIGNALLED );
		if( cryptStatusError( status ) )
			return( status );
		iCryptContext = iCryptCert;
		}

	/* Check the signer details and signature */
	status = checkCert( certInfoPtr, issuerCertInfoPtr, FALSE,
						&certInfoPtr->errorLocus, &certInfoPtr->errorType );
	if( issuerCertInfoPtr != certInfoPtr )
		krnlReleaseObject( issuerCertInfoPtr->objectHandle );
	if( cryptStatusError( status ) )
		return( status );
	if( ( certInfoPtr->flags & CERT_FLAG_SIGCHECKED ) || \
		cryptStatusOK( \
			krnlSendMessage( certInfoPtr->ownerHandle, IMESSAGE_SETATTRIBUTE,
							 &certInfoPtr->objectHandle, 
							 CRYPT_IATTRIBUTE_CERT_CHECKTRUST ) ) )
		/* We've already checked the signature or it's an implicitly trusted 
		   cert, we don't have to go any further */
		return( CRYPT_OK );
	status = checkX509signature( certInfoPtr->certificate, 
								 certInfoPtr->certificateSize, NULL, NULL,
								 iCryptContext, formatInfo );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_NUM1 ) ? \
				CRYPT_ARGERROR_OBJECT : status );
	certInfoPtr->flags |= CERT_FLAG_SIGCHECKED;
	return( CRYPT_OK );
	}

/* Check the validity of a cert object, either against an issuing key/
   certificate or against a CRL */

int checkCertValidity( CERT_INFO *certInfoPtr, const CRYPT_HANDLE sigCheckKey )
	{
	CRYPT_CONTEXT iCryptContext;
	CRYPT_CERTTYPE_TYPE sigCheckKeyType = CRYPT_CERTTYPE_NONE;
	CERT_INFO *issuerCertInfoPtr = NULL;
	OBJECT_TYPE type;
	const int formatInfo = \
				( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT ) ? 1 : \
				( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST ) ? ( 0 | 0x80 ) : \
				CRYPT_UNUSED;
	int status;

	assert( certInfoPtr->certificate != NULL || \
			certInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE || \
			certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE );

	/* If there's no signature checking key supplied, the cert must be self-
	   signed, either an implicitly self-signed object like a cert chain or
	   an explicitly self-signed object like a cert request or self-signed
	   cert */
	if( sigCheckKey == CRYPT_UNUSED )
		{
		/* If it's a cert chain, it's a (complex) self-signed object 
		   containing more than one cert so we need a special function to 
		   check the entire chain */
		if( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )
			return( checkCertChain( certInfoPtr ) );

		/* It's an explicitly self-signed object */
		return( checkSelfSignedCert( certInfoPtr, formatInfo ) );
		}

	/* Find out what the sig.check object is */
	status = krnlSendMessage( sigCheckKey, IMESSAGE_GETATTRIBUTE, &type, 
							  CRYPT_IATTRIBUTE_TYPE );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ARGERROR_VALUE : status );
	if( type == OBJECT_TYPE_CERTIFICATE )
		krnlSendMessage( sigCheckKey, IMESSAGE_GETATTRIBUTE, 
						 &sigCheckKeyType, CRYPT_CERTINFO_CERTTYPE );

	/* Perform a general validity check on the object being checked and the
	   associated verification object.  This is somewhat more strict than 
	   the kernel checks since the kernel only knows about valid subtypes 
	   but not that some subtypes are only valid in combination with some 
	   types of object being checked */
	switch( type )
		{
		case OBJECT_TYPE_CERTIFICATE:
		case OBJECT_TYPE_CONTEXT:
			break;

		case OBJECT_TYPE_KEYSET:
			/* A keyset can only be used as a source of revocation 
			   information for checking a certificate or to populate the
			   status fields of an RTCS/OCSP response */
			if( certInfoPtr->type != CRYPT_CERTTYPE_CERTIFICATE && \
				certInfoPtr->type != CRYPT_CERTTYPE_ATTRIBUTE_CERT && \
				certInfoPtr->type != CRYPT_CERTTYPE_CERTCHAIN && \
				certInfoPtr->type != CRYPT_CERTTYPE_RTCS_RESPONSE && \
				certInfoPtr->type != CRYPT_CERTTYPE_OCSP_RESPONSE )
				return( CRYPT_ARGERROR_VALUE );
			break;

		case OBJECT_TYPE_SESSION:
			/* An (RTCS or OCSP) session can only be used as a source of 
			   validity/revocation information for checking a certificate */
			if( certInfoPtr->type != CRYPT_CERTTYPE_CERTIFICATE && \
				certInfoPtr->type != CRYPT_CERTTYPE_ATTRIBUTE_CERT && \
				certInfoPtr->type != CRYPT_CERTTYPE_CERTCHAIN )
				return( CRYPT_ARGERROR_VALUE );
			break;

		default:
			return( CRYPT_ARGERROR_VALUE );
		}

	/* If the checking key is a CRL, a keyset that may contain a CRL, or an
	   RTCS or OCSP session, then this is a validity/revocation check that 
	   works rather differently from a straight signature check */
	if( type == OBJECT_TYPE_CERTIFICATE && \
		sigCheckKeyType == CRYPT_CERTTYPE_CRL )
		return( checkCRL( certInfoPtr, sigCheckKey ) );
	if( type == OBJECT_TYPE_KEYSET )
		{
		BYTE issuerID[ CRYPT_MAX_HASHSIZE ];

		/* If it's an RTCS or OCSP response, use the certificate store to fill 
		   in the status information fields */
		if( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE )
			return( checkRTCSResponse( certInfoPtr, sigCheckKey ) );
		if( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE )
			return( checkOCSPResponse( certInfoPtr, sigCheckKey ) );

		assert( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
				certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \
				certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );

		/* Generate the issuerID for this cert and check whether it's present 
		   in the CRL.  Since all we're interested in is a yes/no answer, we 
		   tell the keyset to perform a check only */
		status = generateCertID( certInfoPtr->issuerDNptr,
								 certInfoPtr->issuerDNsize, 
								 certInfoPtr->cCertCert->serialNumber, 
								 certInfoPtr->cCertCert->serialNumberLength, 
								 issuerID );
		if( cryptStatusOK( status ) )
			{
			MESSAGE_KEYMGMT_INFO getkeyInfo;

			setMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_ISSUERID, 
								   issuerID, KEYID_SIZE, NULL, 0, 
								   KEYMGMT_FLAG_CHECK_ONLY );
			status = krnlSendMessage( sigCheckKey, IMESSAGE_KEY_GETKEY, 
									  &getkeyInfo, 
									  KEYMGMT_ITEM_REVOCATIONINFO );

			/* Reverse the results of the check: OK -> certificate revoked, 
			   not found -> certificate not revoked */
			if( cryptStatusOK( status ) )
				status = CRYPT_ERROR_INVALID;
			else
				if( status == CRYPT_ERROR_NOTFOUND )
					status = CRYPT_OK;
			}

		return( status );
		}
	if( type == OBJECT_TYPE_SESSION )
		return( checkResponder( certInfoPtr, sigCheckKey ) );

	/* If we've been given a self-signed cert, make sure that the sig.check 
	   key is the same as the cert.  To test this we have to compare both 
	   the signing key and, if the sig check object is a cert, the cert */
	if( certInfoPtr->flags & CERT_FLAG_SELFSIGNED )
		{
		RESOURCE_DATA msgData;
		BYTE keyID[ KEYID_SIZE ];

		/* Check that the key in the cert and the key in the sig.check object 
		   are identical */
		setMessageData( &msgData, keyID, KEYID_SIZE );
		status = krnlSendMessage( sigCheckKey, IMESSAGE_GETATTRIBUTE_S, 
								  &msgData, CRYPT_IATTRIBUTE_KEYID );
		if( cryptStatusOK( status ) )
			status = krnlSendMessage( certInfoPtr->objectHandle, 
									  IMESSAGE_COMPARE, &msgData,
									  MESSAGE_COMPARE_KEYID );
		if( cryptStatusError( status ) )
			return( CRYPT_ARGERROR_VALUE );

		/* If the sig.check object is a cert (even though what's being 
		   checked is already a self-signed cert), check that it's identical 
		   to the cert being checked (which it must be if the cert is self-
		   signed).  This may be somewhat stricter than required, but it'll 
		   weed out technically valid but questionable combinations like a 
		   cert request being used to validate a cert and misleading ones 
		   such as one cert chain being used to check a second chain */
		if( type == OBJECT_TYPE_CERTIFICATE )
			{
			status = krnlSendMessage( certInfoPtr->objectHandle, 
									  IMESSAGE_COMPARE, ( void * ) &sigCheckKey, 
									  MESSAGE_COMPARE_CERTOBJ );
			if( cryptStatusError( status ) )
				return( CRYPT_ARGERROR_VALUE );
			}

		/* If it's a cert chain, it's a (complex) self-signed object 
		   containing more than one cert so we need a special function to check 
		   the entire chain */
		if( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )
			return( checkCertChain( certInfoPtr ) );

		/* Check the signer details and signature.  Issuer and subject cert 
		   info is the same, since it's a self-signed cert */
		status = checkCert( certInfoPtr, certInfoPtr, FALSE,
							&certInfoPtr->errorLocus,
							&certInfoPtr->errorType );
		if( cryptStatusError( status ) )
			return( status );
		if( ( certInfoPtr->flags & CERT_FLAG_SIGCHECKED ) || \
			cryptStatusOK( \
				krnlSendMessage( certInfoPtr->ownerHandle, IMESSAGE_SETATTRIBUTE,
								 &certInfoPtr->objectHandle, 
								 CRYPT_IATTRIBUTE_CERT_CHECKTRUST ) ) )
			/* We've already checked the signature or it's an implicitly 
			   trusted cert, we don't have to go any further */
			return( CRYPT_OK );
		status = checkX509signature( certInfoPtr->certificate, 
									 certInfoPtr->certificateSize, NULL, NULL,
									 certInfoPtr->iPubkeyContext, formatInfo );
		if( cryptStatusError( status ) )
			return( ( status == CRYPT_ARGERROR_NUM1 ) ? \
					CRYPT_ARGERROR_OBJECT : status );
		certInfoPtr->flags |= CERT_FLAG_SIGCHECKED;
		return( CRYPT_OK );
		}

	/* The signature check key may be a certificate or a context.  If it's 
	   a cert, we get the issuer cert info and extract the context from it 
	   before continuing */
	if( type == OBJECT_TYPE_CERTIFICATE )
		{
		/* Get the context from the issuer certificate */
		status = krnlSendMessage( sigCheckKey, IMESSAGE_GETDEPENDENT, 
								  &iCryptContext, OBJECT_TYPE_CONTEXT );
		if( cryptStatusError( status ) )
			return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
					CRYPT_ARGERROR_VALUE : status );

		/* Get the issuer certificate info */
		status = krnlAcquireObject( sigCheckKey, OBJECT_TYPE_CERTIFICATE, 
									( void ** ) &issuerCertInfoPtr, 
									CRYPT_ARGERROR_VALUE );
		if( cryptStatusError( status ) )
			return( status );
		}
	else
		{
		CRYPT_CERTIFICATE localCert;

		iCryptContext = sigCheckKey;

		/* It's a context, we may have a certificate present in it so we try 
		   to extract that and use it as the issuer certificate if possible.  
		   If the issuer cert isn't present this isn't an error, since it 
		   could be just a raw context */
		status = krnlSendMessage( sigCheckKey, IMESSAGE_GETDEPENDENT,
								  &localCert, OBJECT_TYPE_CERTIFICATE );
		if( cryptStatusOK( status ) )
			status = krnlAcquireObject( localCert, OBJECT_TYPE_CERTIFICATE, 
										( void ** ) &issuerCertInfoPtr, 
										CRYPT_ARGERROR_VALUE );
		if( cryptStatusError( status ) )
			/* There's no issuer cert present, all we can do is perform a 
			   pure signature check using the context */
			issuerCertInfoPtr = NULL;
		}

	/* If there's an issuer certificate present, check the validity of the
	   subject cert based on it */
	if( issuerCertInfoPtr != NULL )
		{
		status = checkCert( certInfoPtr, issuerCertInfoPtr, FALSE,
							&certInfoPtr->errorLocus,
							&certInfoPtr->errorType );
		krnlReleaseObject( issuerCertInfoPtr->objectHandle );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Check the signature */
	if( ( certInfoPtr->flags & CERT_FLAG_SIGCHECKED ) || \
		cryptStatusOK( \
			krnlSendMessage( certInfoPtr->ownerHandle, IMESSAGE_SETATTRIBUTE,
							 &certInfoPtr->objectHandle, 
							 CRYPT_IATTRIBUTE_CERT_CHECKTRUST ) ) )
		/* We've already checked the signature or it's an implicitly 
		   trusted cert, we don't have to go any further */
		return( CRYPT_OK );
	status = checkX509signature( certInfoPtr->certificate, 
								 certInfoPtr->certificateSize, NULL, NULL, 
								 iCryptContext, formatInfo );
	if( cryptStatusOK( status ) )
		/* The signature is OK, we don't need to check it again */
		certInfoPtr->flags |= CERT_FLAG_SIGCHECKED;
	else
		if( status == CRYPT_ARGERROR_NUM1 )
			status = CRYPT_ARGERROR_VALUE;
	return( status );
	}

⌨️ 快捷键说明

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