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

📄 ca_misc.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 2 页
字号:
		{
		sMemOpen( &stream, errorData, MAX_CERT_SIZE );
		writeSequence( &stream, sizeofObject( 1 ) + sizeofObject( 31 ) );
		writeShortInteger( &stream, -( CRYPT_ERROR_FAILED ), DEFAULT_TAG );
		status = writeCharacterString( &stream, 
									   "Error writing error information", 31,
									   BER_STRING_UTF8 );
		if( cryptStatusOK( status ) )
			errorDataLength = stell( &stream );
		sMemDisconnect( &stream );
		}
	ENSURES( cryptStatusOK( status ) );

	/* Update the certificate store log with the error information as the 
	   data value */
	return( updateCertLog( dbmsInfo, CRYPT_CERTACTION_ERROR, 
						   certID, certIDlength, reqCertID, reqCertIDlength, 
						   subjCertID, subjCertIDlength, 
						   errorData, errorDataLength, DBMS_UPDATE_NORMAL ) );
	}

RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
int updateCertErrorLogMsg( INOUT DBMS_INFO *dbmsInfo, 
						   IN_ERROR const int errorStatus,
						   IN_STRING const char *errorString )
	{
	assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );

	return( updateCertErrorLog( dbmsInfo, errorStatus, errorString,
								NULL, 0, NULL, 0, NULL, 0, NULL, 0 ) );
	}

/****************************************************************************
*																			*
*							Miscellaneous CA Functions						*
*																			*
****************************************************************************/

/* Get the PKI user that originally authorised the issuance of a certificate.  
   This can involve chaining back through multiple generations of 
   certificates, for example to check authorisation on a revocation request 
   we might have to go through:

	rev_req:	get reqCertID = update_req
	update_req:	get reqCertID = cert_req
	cert_req:	get reqCertID = init_req
	init_req:	get reqCertID = pki_user */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \
int caGetIssuingUser( INOUT DBMS_INFO *dbmsInfo, 
					  OUT_HANDLE_OPT CRYPT_CERTIFICATE *iPkiUser,
					  IN_BUFFER( initialCertIDlength ) const char *initialCertID, 
					  IN_LENGTH_SHORT_MIN( ENCODED_DBXKEYID_SIZE ) \
						const int initialCertIDlength, 
					  INOUT ERROR_INFO *errorInfo )
	{
	char certID[ ENCODED_DBXKEYID_SIZE + 8 ];
	int certIDlength, chainingLevel, dummy, status;

	assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );
	assert( isWritePtr( iPkiUser, sizeof( CRYPT_CERTIFICATE ) ) );
	assert( isReadPtr( initialCertID, ENCODED_DBXKEYID_SIZE ) );

	REQUIRES( initialCertIDlength >= ENCODED_DBXKEYID_SIZE && \
			  initialCertIDlength < MAX_INTLENGTH_SHORT );
	REQUIRES( errorInfo != NULL );

	/* Clear return value */
	*iPkiUser = CRYPT_ERROR;

	/* Walk through the chain of updates in the certificate store log until 
	   we find the PKI user that authorised the first certificate issue */
	memcpy( certID, initialCertID, initialCertIDlength );
	certIDlength = initialCertIDlength;
	for( chainingLevel = 0; chainingLevel < FAILSAFE_ITERATIONS_MED; 
		 chainingLevel++ )
		{
		BOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;
		char certData[ MAX_QUERY_RESULT_SIZE + 8 ];
		int certDataLength;

		/* Find out whether this is a PKI user.  The comparison for the
		   action type is a bit odd since some back-ends will return the
		   action as text and some as a binary numeric value.  Rather than
		   relying on the back-end glue code to perform the appropriate
		   conversion we just check for either value type */
		initBoundData( boundDataPtr );
		setBoundData( boundDataPtr, 0, certID, certIDlength );
		status = dbmsQuery(
			"SELECT action FROM certLog WHERE certID = ?",
							certData, MAX_QUERY_RESULT_SIZE, &certDataLength, 
							boundDataPtr, DBMS_CACHEDQUERY_NONE, 
							DBMS_QUERY_NORMAL );
		if( cryptStatusError( status ) )
			return( status );
		if( certData[ 0 ] == CRYPT_CERTACTION_ADDUSER || \
			certData[ 0 ] == TEXTCH_CERTACTION_ADDUSER )
			{
			/* We've found the PKI user, we're done */
			break;
			}

		/* Find the certificate that was issued, recorded either as a
		   CERTACTION_CERT_CREATION for a multi-phase CMP-based certificate
		   creation or a CERTACTION_ISSUE_CERT for a one-step creation */
		status = dbmsQuery(
			"SELECT reqCertID FROM certLog WHERE certID = ?",
							certData, MAX_QUERY_RESULT_SIZE, &certDataLength, 
							boundDataPtr, DBMS_CACHEDQUERY_NONE, 
							DBMS_QUERY_NORMAL );
		if( cryptStatusError( status ) )
			return( status );
		certIDlength = min( certDataLength, ENCODED_DBXKEYID_SIZE );
		memcpy( certID, certData, certIDlength );

		/* Find the request to issue this certificate.  For a CMP-based issue
		   this will have an authorising object (found in the next iteration
		   through the loop), for a one-step issue it won't */
		initBoundData( boundDataPtr );
		setBoundData( boundDataPtr, 0, certID, certIDlength );
		status = dbmsQuery(
			"SELECT reqCertID FROM certLog WHERE certID = ?",
							certData, MAX_QUERY_RESULT_SIZE, &certDataLength, 
							boundDataPtr, DBMS_CACHEDQUERY_NONE, 
							DBMS_QUERY_NORMAL );
		if( cryptStatusError( status ) )
			return( status );
		certIDlength = min( certDataLength, ENCODED_DBXKEYID_SIZE );
		memcpy( certID, certData, certIDlength );
		}
	if( chainingLevel >= FAILSAFE_ITERATIONS_MED )
		{
		/* We've chained through too many entries, bail out */
		return( CRYPT_ERROR_OVERFLOW );
		}

	/* We've found the original PKI user, get the user information */
	return( getItemData( dbmsInfo, iPkiUser, &dummy, KEYMGMT_ITEM_PKIUSER,
						 CRYPT_IKEYID_CERTID, certID, certIDlength, 
						 KEYMGMT_FLAG_NONE, errorInfo ) );
	}

/****************************************************************************
*																			*
*						CA Certificate Management Interface					*
*																			*
****************************************************************************/

/* Perform a certificate management operation */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int certMgmtFunction( INOUT KEYSET_INFO *keysetInfoPtr,
							 OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,
							 IN_HANDLE_OPT const CRYPT_CERTIFICATE caKey,
							 IN_HANDLE_OPT const CRYPT_CERTIFICATE request,
							 IN_ENUM( CRYPT_CERTACTION ) \
								const CRYPT_CERTACTION_TYPE action )
	{
	BOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;
	DBMS_INFO *dbmsInfo = keysetInfoPtr->keysetDBMS;
	char reqCertID[ ENCODED_DBXKEYID_SIZE + 8 ];
	int reqCertIDlength, status;

	assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
	assert( ( iCertificate == NULL ) || \
			isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );

	REQUIRES( keysetInfoPtr->type == KEYSET_DBMS );
	REQUIRES( ( caKey == CRYPT_UNUSED ) || isHandleRangeValid( caKey ) );
	REQUIRES( ( request == CRYPT_UNUSED ) || isHandleRangeValid( request ) );
	REQUIRES( action > CRYPT_CERTACTION_NONE && \
			  action < CRYPT_CERTACTION_LAST );

	/* In order for various SQL query strings to use the correct values the
	   type values have to match their text equivalents defined at the start
	   of this file.  Since we can't check this at compile time we have to
	   do it here via an assertion */
	assert( TEXT_CERTTYPE_REQUEST_CERT[ 0 ] - '0' == \
			CRYPT_CERTTYPE_REQUEST_CERT );
	assert( TEXT_CERTTYPE_REQUEST_REVOCATION[ 0 ] - '0' == \
			CRYPT_CERTTYPE_REQUEST_REVOCATION );
	assert( TEXT_CERTACTION_CREATE[ 0 ] - '0' == \
			CRYPT_CERTACTION_CREATE );
	assert( TEXTCH_CERTACTION_ADDUSER - '0' == \
			CRYPT_CERTACTION_ADDUSER );
	assert( TEXT_CERTACTION_REQUEST_CERT[ 0 ] - '0' == \
			CRYPT_CERTACTION_REQUEST_CERT );
	assert( TEXTCH_CERTACTION_REQUEST_CERT - '0' == \
			CRYPT_CERTACTION_REQUEST_CERT );
	assert( TEXT_CERTACTION_REQUEST_RENEWAL[ 0 ] - '0' == \
			CRYPT_CERTACTION_REQUEST_RENEWAL );
	assert( TEXTCH_CERTACTION_REQUEST_RENEWAL - '0' == \
			CRYPT_CERTACTION_REQUEST_RENEWAL );
	assert( TEXT_CERTACTION_CERT_CREATION[ 0 ] - '0' == \
			CRYPT_CERTACTION_CERT_CREATION / 10 );
	assert( TEXT_CERTACTION_CERT_CREATION[ 1 ] - '0' == \
			CRYPT_CERTACTION_CERT_CREATION % 10 );

	/* Clear return value */
	if( iCertificate != NULL )
		*iCertificate = CRYPT_ERROR;

	/* If it's a simple certificate expire or cleanup, there are no 
	   parameters to check so we can perform the action immediately */
	if( action == CRYPT_CERTACTION_EXPIRE_CERT || \
		action == CRYPT_CERTACTION_CLEANUP )
		{
		REQUIRES( caKey == CRYPT_UNUSED );
		REQUIRES( request == CRYPT_UNUSED );

		return( caCleanup( dbmsInfo, action, KEYSET_ERRINFO ) );
		}

	/* If it's the completion of a certificate creation, process it */
	if( action == CRYPT_CERTACTION_CERT_CREATION_COMPLETE || \
		action == CRYPT_CERTACTION_CERT_CREATION_DROP || \
		action == CRYPT_CERTACTION_CERT_CREATION_REVERSE )
		{
		REQUIRES( caKey == CRYPT_UNUSED );

		return( caIssueCertComplete( dbmsInfo, request, action, 
									 KEYSET_ERRINFO ) );
		}

	/* Check that the CA key that we've been passed is in order.  These
	   checks are performed automatically during the issue process by the
	   kernel when we try and convert the request into a certificate, 
	   however we perform them explicitly here so that we can return a more 
	   meaningful error message to the caller */
	if( action == CRYPT_CERTACTION_ISSUE_CRL )
		{
		int value;

		/* If we're issuing a CRL, the key must be capable of CRL signing */
		status = krnlSendMessage( caKey, IMESSAGE_GETATTRIBUTE, &value,
								  CRYPT_CERTINFO_KEYUSAGE );
		if( cryptStatusError( status ) || \
			!( value & CRYPT_KEYUSAGE_CRLSIGN ) )
			{
			retExtArg( CAMGMT_ARGERROR_CAKEY, 
					   ( CAMGMT_ARGERROR_CAKEY, KEYSET_ERRINFO, 
						 "CA certificate isn't valid for CRL signing" ) );
			}
		}
	else
		{
		/* For anything other than a revocation action (which just updates 
		   the certificate store without doing anything else) the key must 
		   be a CA key */
		if( action != CRYPT_CERTACTION_REVOKE_CERT && \
			cryptStatusError( \
				krnlSendMessage( caKey, IMESSAGE_CHECK, NULL,
								 MESSAGE_CHECK_CA ) ) )
			{
			retExtArg( CAMGMT_ARGERROR_CAKEY, 
					   ( CAMGMT_ARGERROR_CAKEY, KEYSET_ERRINFO, 
						 "CA certificate isn't valid for certificate "
						 "signing" ) );
			}
		}

	/* If it's a CRL issue it's a read-only operation on the CRL store for 
	   which we only need the CA certificate (there's no request involved) */
	if( action == CRYPT_CERTACTION_ISSUE_CRL )
		{
		REQUIRES( request == CRYPT_UNUSED );

		return( caIssueCRL( dbmsInfo, iCertificate, caKey, KEYSET_ERRINFO ) );
		}

	/* We're processing an action that requires an explicit certificate 
	   request, perform further checks on the request */
	if( !checkRequest( request, action ) )
		{
		retExtArg( CAMGMT_ARGERROR_REQUEST, 
				   ( CAMGMT_ARGERROR_REQUEST, KEYSET_ERRINFO, 
					 "Certificate request information "
					 "inconsistent/invalid" ) );
		}

	/* Make sure that the request is present in the request table in order 
	   to issue a certificate for it.  Again, this will be checked later but 
	   we can return a more meaningful error here */
	status = getKeyID( reqCertID, ENCODED_DBXKEYID_SIZE, &reqCertIDlength, 
					   request, CRYPT_CERTINFO_FINGERPRINT_SHA );
	if( cryptStatusError( status ) )
		return( CAMGMT_ARGERROR_REQUEST );
	initBoundData( boundDataPtr );
	setBoundData( boundDataPtr, 0, reqCertID, reqCertIDlength );
	status = dbmsQuery(
		"SELECT certData FROM certRequests WHERE certID = ?",
						NULL, 0, NULL, boundDataPtr, 
						DBMS_CACHEDQUERY_NONE, DBMS_QUERY_CHECK );
	if( cryptStatusError( status ) )
		{
		retExt( CRYPT_ERROR_NOTFOUND, 
				( CRYPT_ERROR_NOTFOUND, KEYSET_ERRINFO, 
				  "Certificate request doesn't correspond to any existing "
				  "request in the certificate store" ) );
		}

	/* If it's a revocation request, process it */
	if( action == CRYPT_CERTACTION_REVOKE_CERT )
		{
		REQUIRES( caKey == CRYPT_UNUSED );

		return( caRevokeCert( dbmsInfo, request, CRYPT_UNUSED,
							  CRYPT_CERTACTION_REVOKE_CERT, KEYSET_ERRINFO ) );
		}

	/* It's a certificate issue request, issue the certificate */
	REQUIRES( action == CRYPT_CERTACTION_ISSUE_CERT || \
			  action == CRYPT_CERTACTION_CERT_CREATION );
	REQUIRES( isHandleRangeValid( caKey ) );

	return( caIssueCert( dbmsInfo, iCertificate, caKey, request, action, 
						 KEYSET_ERRINFO ) );
	}

/* Set up the function pointers to the keyset methods */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int initDBMSCA( INOUT KEYSET_INFO *keysetInfoPtr )
	{
	assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );

	REQUIRES( keysetInfoPtr->type == KEYSET_DBMS );

	keysetInfoPtr->keysetDBMS->certMgmtFunction = certMgmtFunction;

	return( CRYPT_OK );
	}
#endif /* USE_DBMS */

⌨️ 快捷键说明

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