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

📄 ca_add.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*																			*
*					  cryptlib DBMS CA Cert Add Interface					*
*						Copyright Peter Gutmann 1996-2004					*
*																			*
****************************************************************************/

#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#if defined( INC_ALL )
  #include "crypt.h"
  #include "keyset.h"
  #include "dbms.h"
  #include "asn1.h"
  #include "rpc.h"
#elif defined( INC_CHILD )
  #include "../crypt.h"
  #include "../keyset/keyset.h"
  #include "../keyset/dbms.h"
  #include "../misc/asn1.h"
  #include "../misc/rpc.h"
#else
  #include "crypt.h"
  #include "keyset/keyset.h"
  #include "keyset/dbms.h"
  #include "misc/asn1.h"
  #include "misc/rpc.h"
#endif /* Compiler-specific includes */

#ifdef USE_DBMS

/****************************************************************************
*																			*
*								Utility Functions							*
*																			*
****************************************************************************/

/* Check that the request we've been passed is in order */

BOOLEAN checkRequest( const CRYPT_CERTIFICATE iCertRequest,
					  const CRYPT_CERTACTION_TYPE action )
	{
	RESOURCE_DATA msgData;
	int certType, value, status;

	/* Make sure that the request type is consistent with the operation
	   being performed */
	status = krnlSendMessage( iCertRequest, IMESSAGE_GETATTRIBUTE,
							  &certType, CRYPT_CERTINFO_CERTTYPE );
	if( cryptStatusError( status ) )
		return( FALSE );
	switch( action )
		{
		case CRYPT_CERTACTION_CERT_CREATION:
		case CRYPT_CERTACTION_ISSUE_CERT:
			if( certType != CRYPT_CERTTYPE_CERTREQUEST && \
				certType != CRYPT_CERTTYPE_REQUEST_CERT )
				return( FALSE );
			break;

		case CRYPT_CERTACTION_REVOKE_CERT:
			if( certType != CRYPT_CERTTYPE_REQUEST_REVOCATION )
				return( FALSE );
			break;

		case CRYPT_CERTACTION_NONE:
			/* We're performing a straight add of a request to the store,
			   any request type is permitted */
			break;

		default:
			assert( NOTREACHED );
			return( FALSE );
		}

	/* Make sure that the request is completed and valid.  We don't check
	   the signature on revocation requests since they aren't signed, and
	   have to be careful with CRMF requests, which can be unsigned for
	   encryption-only keys */
	status = krnlSendMessage( iCertRequest, IMESSAGE_GETATTRIBUTE,
							  &value, CRYPT_CERTINFO_IMMUTABLE );
	if( cryptStatusError( status ) || !value )
		return( FALSE );
	switch( certType )
		{
		case CRYPT_CERTTYPE_REQUEST_CERT:
			if( cryptStatusOK( \
					krnlSendMessage( iCertRequest, IMESSAGE_GETATTRIBUTE,
									 &value, CRYPT_CERTINFO_SELFSIGNED ) ) && \
				!value )
				{
				/* It's an unsigned CRMF request, make sure that it really 
				   is an encryption-only key */
				status = krnlSendMessage( iCertRequest, IMESSAGE_GETATTRIBUTE,
										  &value, CRYPT_CERTINFO_KEYUSAGE );
				if( cryptStatusOK( status ) && \
					( value & ( CRYPT_KEYUSAGE_DIGITALSIGNATURE | \
								CRYPT_KEYUSAGE_NONREPUDIATION ) ) )
					return( FALSE );
				break;
				}

			/* Fall through */

		case CRYPT_CERTTYPE_CERTREQUEST:
			status = krnlSendMessage( iCertRequest, IMESSAGE_CRT_SIGCHECK,
									  NULL, CRYPT_UNUSED );
			if( cryptStatusError( status ) )
				return( FALSE );
			break;

		case CRYPT_CERTTYPE_REQUEST_REVOCATION:
			/* Revocation requests are unsigned so we can't perform a sig.
			   check on them */
			break;

		default:
			assert( NOTREACHED );
			return( FALSE );
		}

	/* Check that required parameters are present.  This is necessary for
	   CRMF requests where every single parameter is optional, for our use
	   we require that a cert request contains at least a subject DN and
	   public key and a revocation request contains at least an issuer DN and
	   serial number */
	switch( certType )
		{
		case CRYPT_CERTTYPE_CERTREQUEST:
		case CRYPT_CERTTYPE_REQUEST_CERT:
			setMessageData( &msgData, NULL, 0 );
			status = krnlSendMessage( iCertRequest, IMESSAGE_GETATTRIBUTE_S,
									  &msgData, CRYPT_IATTRIBUTE_SUBJECT );
			if( cryptStatusError( status ) )
				return( FALSE );
			setMessageData( &msgData, NULL, 0 );
			status = krnlSendMessage( iCertRequest, IMESSAGE_GETATTRIBUTE_S,
									  &msgData, CRYPT_IATTRIBUTE_SPKI );
			if( cryptStatusError( status ) )
				return( FALSE );
			break;

		case CRYPT_CERTTYPE_REQUEST_REVOCATION:
			setMessageData( &msgData, NULL, 0 );
			status = krnlSendMessage( iCertRequest, IMESSAGE_GETATTRIBUTE_S,
									  &msgData, 
									  CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
			if( cryptStatusError( status ) )
				return( FALSE );
			break;

		default:
			assert( NOTREACHED );
			return( FALSE );
		}

	return( TRUE );
	}

/* Check that a revocation request is consistent with information held in the
   cert store */

static int checkRevRequest( DBMS_INFO *dbmsInfo,
							const CRYPT_CERTIFICATE iCertRequest )
	{
	char certID[ DBXKEYID_BUFFER_SIZE ], issuerID[ DBXKEYID_BUFFER_SIZE ];
	int length, status;

	/* Check that the cert being referred to in the request is present and
	   active */
	status = length = getKeyID( issuerID, iCertRequest,
								CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
	if( !cryptStatusError( status ) )
		status = dbmsQuery(
			"SELECT certData FROM certificates WHERE issuerID = ?",
							NULL, 0, issuerID, length, 0,
							DBMS_CACHEDQUERY_ISSUERID, DBMS_QUERY_CHECK );
	if( cryptStatusOK( status ) )
		return( CRYPT_OK );

	/* The cert isn't an active cert, it's either not present or not active,
	   return an appropriate error code.  If this request has been entered
	   into the cert log then it's a duplicate request, otherwise it's a
	   request to revoke a non-present cert (either that or something really
	   obscure which is best reported as a non-present cert problem) */
	status = length = getKeyID( certID, iCertRequest,
								CRYPT_CERTINFO_FINGERPRINT_SHA );
	if( !cryptStatusError( status ) )
		status = dbmsQuery(
			"SELECT certData FROM certLog WHERE certID = ?",
							NULL, 0, certID, length, 0,
							DBMS_CACHEDQUERY_NONE, DBMS_QUERY_CHECK );
	return( cryptStatusOK( status ) ? \
			CRYPT_ERROR_DUPLICATE : CRYPT_ERROR_NOTFOUND );
	}

/****************************************************************************
*																			*
*								Cert Add Functions							*
*																			*
****************************************************************************/

/* Add a new PKI user to the cert store */

int caAddPKIUser( DBMS_INFO *dbmsInfo, const CRYPT_CERTIFICATE iPkiUser )
	{
	RESOURCE_DATA msgData;
	BYTE certData[ MAX_CERT_SIZE ];
	char certID[ DBXKEYID_BUFFER_SIZE ];
	int certDataLength, status;

	assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );
	assert( isHandleRangeValid( iPkiUser ) );

	/* Extract the information we need from the PKI user object.  In
	   addition to simply obtaining the information for logging purposes we
	   also need to perform this action to tell the cert management code to
	   fill in the remainder of the (implicitly-added) user info before we
	   start querying fields as we add it to the cert store.  Because of this
	   we also need to place the certID fetch after the object export, since
	   it's in an incomplete state before this point */
	setMessageData( &msgData, certData, MAX_CERT_SIZE );
	status = krnlSendMessage( iPkiUser, IMESSAGE_CRT_EXPORT, &msgData,
							  CRYPT_ICERTFORMAT_DATA );
	if( cryptStatusOK( status ) )
		status = getKeyID( certID, iPkiUser, CRYPT_CERTINFO_FINGERPRINT_SHA );
	if( cryptStatusError( status ) )
		return( status );
	certDataLength = msgData.length;

	/* Update the cert store */
	status = addCert( dbmsInfo, iPkiUser, CRYPT_CERTTYPE_PKIUSER,
					  CERTADD_NORMAL, DBMS_UPDATE_BEGIN );
	if( cryptStatusOK( status ) )
		status = updateCertLog( dbmsInfo, CRYPT_CERTACTION_ADDUSER, certID,
								NULL, NULL, certData, certDataLength,
								DBMS_UPDATE_COMMIT );
	else
		/* Something went wrong, abort the transaction */

⌨️ 快捷键说明

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