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

📄 certrd.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 4 页
字号:
/****************************************************************************
*																			*
*							Certificate Read Routines						*
*						Copyright Peter Gutmann 1996-2001					*
*																			*
****************************************************************************/

#include <stdlib.h>
#include <string.h>
#if defined( INC_ALL ) ||  defined( INC_CHILD )
  #include "asn1.h"
  #include "asn1objs.h"
  #include "asn1oid.h"
  #include "cert.h"
#else
  #include "keymgmt/asn1.h"
  #include "keymgmt/asn1objs.h"
  #include "keymgmt/asn1oid.h"
  #include "keymgmt/cert.h"
#endif /* Compiler-specific includes */

/* Context-specific tags for certificates */

enum { CTAG_CE_VERSION, CTAG_CE_ISSUERUNIQUEID, CTAG_CE_SUBJECTUNIQUEID,
	   CTAG_CE_EXTENSIONS };

/* Context-specific tags for attribute certificates */

enum { CTAG_AC_BASECERTIFICATEID, CTAG_AC_ENTITYNAME,
	   CTAG_AC_OBJECTDIGESTINFO };

/* Context-specific tags for certification requests */

enum { CTAG_CR_ATTRIBUTES };

/* Context-specific tags for CRMF certification requests */

enum { CTAG_CF_VERSION, CTAG_CF_SERIALNUMBER, CTAG_CF_SIGNINGALG, 
	   CTAG_CF_ISSUER, CTAG_CF_VALIDITY, CTAG_CF_SUBJECT, CTAG_CF_PUBLICKEY,
	   CTAG_CF_ISSUERUID, CTAG_CF_SUBJECTUID, CTAG_CF_EXTENSIONS };

/* Context-specific tags for OCSP requests */

enum { CTAG_RQ_VERSION, CTAG_RQ_DUMMY, CTAG_RQ_EXTENSIONS };

/* Context-specific tags for OCSP responses */

enum { CTAG_RP_VERSION, CTAG_RP_EXTENSIONS };

/* Context-specific tags for OCSP certificate identifier types */

enum { OCSP_IDTYPE_ISSUERANDSERIALNUMBER, OCSP_IDTYPE_CERTIFICATE, 
	   OCSP_IDTYPE_DUMMY, OCSP_IDTYPE_CERTHASH };

/* OCSP cert status values */

enum { OCSP_STATUS_NOTREVOKED, OCSP_STATUS_REVOKED, OCSP_STATUS_UNKNOWN };

/* Prototypes for functions in certstr.c */

int convertEmailAddress( CERT_INFO *certInfoPtr );

/****************************************************************************
*																			*
*						Revocation Information Functions					*
*																			*
****************************************************************************/

/* Find an entry in a revocation list */

static int findRevocationEntry( REVOCATION_INFO *listPtr, 
								REVOCATION_INFO **insertPoint,
								const void *value, const int valueLength )
	{
	REVOCATION_INFO *prevElement = NULL;

	*insertPoint = NULL;

	/* Find the correct place in the list to insert the new element and check
	   for duplicates.  We sort the entries by serial number (or, more
	   generally, data value) for no adequately explored reason (some 
	   implementations can optimise the searching of CRLs based on this, but 
	   since there's no agreement on whether to do it or not you can't tell 
	   whether it's safe to rely on this) */
	while( listPtr != NULL )
		{
		if( listPtr->dataLength == valueLength )
			{
			const int compareStatus = memcmp( listPtr->data,
											  value, valueLength );

			if( !compareStatus )
				{
				/* We found a matching entry, tell the caller which one it 
				   is */
				*insertPoint = listPtr;
				return( CRYPT_OK );
				}
			if( compareStatus > 0 )
				break;					/* Insert before this point */
			}
		else
			if( listPtr->dataLength > valueLength )
				break;					/* Insert before this point */

		prevElement = listPtr;
		listPtr = listPtr->next;
		}

	/* We can't find a matching entry, return the revocation entry after 
	   which we should insert the new value */
	*insertPoint = prevElement;
	return( CRYPT_ERROR_NOTFOUND );
	}

/* Check whether a cert has been revoked */

int checkRevocation( const CERT_INFO *certInfoPtr, 
					 CERT_INFO *revocationInfoPtr )
	{
	REVOCATION_INFO *revocationEntry;
	int status;

	/* If we're checking against a CRL and the issuers differ, the cert 
	   can't be in this CRL */
	if( revocationInfoPtr->type == CRYPT_CERTTYPE_CRL && \
		( revocationInfoPtr->issuerDNsize != certInfoPtr->issuerDNsize || \
		  memcmp( revocationInfoPtr->issuerDNptr, certInfoPtr->issuerDNptr,
				  revocationInfoPtr->issuerDNsize ) ) )
		return( CRYPT_OK );

	/* Check whether the cert is present in the revocation list */
	if( revocationInfoPtr->type == CRYPT_CERTTYPE_CRL )
		{
		status = findRevocationEntry( revocationInfoPtr->revocations, 
								&revocationEntry, certInfoPtr->serialNumber, 
								certInfoPtr->serialNumberLength );
		if( status == CRYPT_ERROR_NOTFOUND )
			/* No CRL entry, the certificate is OK */
			return( CRYPT_OK );
		}
	else
		{
		BYTE certHash[ CRYPT_MAX_HASHSIZE ];
		int certHashLength;

		assert( revocationInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE );

		/* Get the cert hash and use it to check whether there's an entry
		   for this cert in the list.  We read the cert hash indirectly 
		   since it's computed on demand and may not have been evaluated 
		   yet */
		status = getCertComponent( ( CERT_INFO * ) certInfoPtr, 
								   CRYPT_CERTINFO_FINGERPRINT_SHA,
								   certHash, &certHashLength );
		if( cryptStatusOK( status ) )
			status = findRevocationEntry( revocationInfoPtr->revocations, 
								&revocationEntry, certHash, certHashLength );
		if( status == CRYPT_ERROR_NOTFOUND )
			/* No entry, either good or bad, we can't report anything about
			   the cert */
			return( CRYPT_ERROR_NOTFOUND );
		}

	/* Select the entry which contains the revocation and return the cert's 
	   status.  For CRLs the presence of an entry means the cert is invalid,
	   for OCSP the validity information is contained in the entry.  The
	   unknown status is a bit difficult to report, the best we can do is
	   report notfound since, although the notfound occurred at the responder
	   rather than here */
	revocationInfoPtr->currentRevocation = revocationEntry;
	if( revocationInfoPtr->type == CRYPT_CERTTYPE_CRL )
		return( CRYPT_ERROR_INVALID );
	return( ( revocationInfoPtr->currentRevocation->status == \
				CRYPT_OCSPSTATUS_NOTREVOKED ) ? CRYPT_OK : \
			( revocationInfoPtr->currentRevocation->status == \
				CRYPT_OCSPSTATUS_REVOKED ) ? CRYPT_ERROR_INVALID : \
			CRYPT_ERROR_NOTFOUND );
	}

/* Add an entry to a revocation list */

int addRevocationEntry( REVOCATION_INFO **listHeadPtr, 
						REVOCATION_INFO **newEntryPosition,
						const CRYPT_ATTRIBUTE_TYPE valueType,
						const void *value, const int valueLength )
	{
	REVOCATION_INFO *newElement, *insertPoint;
	int status;

	/* Find the insertion point for the new entry */
	status = findRevocationEntry( *listHeadPtr, &insertPoint, value, 
								  valueLength );
	if( status == CRYPT_OK )
		/* If get an OK status it means we've found an existing entry which
		   matches the one being added, we can't add it again */
		return( CRYPT_ERROR_DUPLICATE );

	/* Allocate memory for the new element and copy the information across */
	if( ( newElement  = ( REVOCATION_INFO * ) \
						malloc( sizeof( REVOCATION_INFO ) ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	memset( newElement, 0, sizeof( REVOCATION_INFO ) );
	if( valueLength > 128 )
		{
		if( ( newElement->dataPtr = malloc( valueLength ) ) == NULL )
			{
			free( newElement );
			return( CRYPT_ERROR_MEMORY );
			}
		}
	else
		newElement->dataPtr = newElement->data;
	newElement->type = valueType;
	memcpy( newElement->dataPtr, value, valueLength );
	newElement->dataLength = valueLength;

	/* Insert the new element into the list */
	if( *listHeadPtr == NULL )
		/* It's an empty list, make this the new list */
		*listHeadPtr = newElement;
	else
		if( insertPoint == NULL )
			{
			/* We're inserting at the start of the list, make this the new
			   first element */
			newElement->next = *listHeadPtr;
			*listHeadPtr = newElement;
			}
		else
			{
			/* Insert the element in the middle or end of the list */
			newElement->next = insertPoint->next;
			insertPoint->next = newElement;
			}
	*newEntryPosition = newElement;

	return( CRYPT_OK );
	}

/* Delete a revocation list */

void deleteRevocationEntries( REVOCATION_INFO **listHeadPtr )
	{
	REVOCATION_INFO *entryListPtr = *listHeadPtr;

	*listHeadPtr = NULL;

	/* Destroy any remaining list items */
	while( entryListPtr != NULL )
		{
		REVOCATION_INFO *itemToFree = entryListPtr;

		entryListPtr = entryListPtr->next;
		if( itemToFree->dataPtr != itemToFree->data )
			{
			zeroise( itemToFree->dataPtr, itemToFree->dataLength );
			free( itemToFree->dataPtr );
			}
		if( itemToFree->attributes != NULL )
			deleteAttributes( &itemToFree->attributes );
		zeroise( itemToFree, sizeof( REVOCATION_INFO ) );
		free( itemToFree );
		}
	}

/* Copy a revocation list */

int copyRevocationEntries( REVOCATION_INFO **destListHeadPtr,
						   const REVOCATION_INFO *srcListPtr,
						   CRYPT_ATTRIBUTE_TYPE *errorLocus, 
						   CRYPT_ERRTYPE_TYPE *errorType )
	{
	const REVOCATION_INFO *srcListCursor;
	REVOCATION_INFO *destListCursor;

	assert( *destListHeadPtr == NULL );	/* Dest.should be empty */

	/* Copy all revocation entries from source to destination */
	for( srcListCursor = srcListPtr; srcListCursor != NULL;
		 srcListCursor = srcListCursor->next )
		{
		REVOCATION_INFO *newElement;

		/* Allocate the new entry and copy the data from the existing one 
		   across.  We don't copy the attributes because there aren't any
		   which should be carried from request to response */
		if( ( newElement = ( REVOCATION_INFO * ) \
						malloc( sizeof( REVOCATION_INFO ) ) ) == NULL )
			return( CRYPT_ERROR_MEMORY );
		memcpy( newElement, srcListCursor, sizeof( REVOCATION_INFO ) );
		if( srcListCursor->dataLength > 128 )
			{
			/* If the ID information doesn't fit into the fixed buffer, 
			   allocate a variable-length one and copy it across */
			if( ( newElement->dataPtr = \
						malloc( srcListCursor->dataLength ) ) == NULL )
				{
				free( newElement );
				return( CRYPT_ERROR_MEMORY );
				}
			memcpy( newElement->dataPtr, srcListCursor->data,
					srcListCursor->dataLength );
			}
		else
			newElement->dataPtr = newElement->data;
		newElement->attributes = NULL;
		newElement->next = NULL;

		/* Set the status to 'unknown' by default, this means that any 
		   entries which we can't do anything with automatically get the
		   correct status associated with them */
		newElement->status = CRYPT_OCSPSTATUS_UNKNOWN;

		/* Link the new element into the list */
		if( *destListHeadPtr == NULL )
			*destListHeadPtr = destListCursor = newElement;
		else
			{
			destListCursor->next = newElement;
			destListCursor = newElement;
			}
		}

	return( CRYPT_OK );
	}

/* Read a CRL entry:

	RevokedCert ::= SEQUENCE {
			userCertificate		CertificalSerialNumber,
			revocationDate		UTCTime
			extensions			Extensions OPTIONAL,
			} */

static int readCRLentry( STREAM *stream, REVOCATION_INFO **listHeadPtr,
						 CERT_INFO *certInfoPtr )
	{
	REVOCATION_INFO *currentEntry;
	BYTE serialNumber[ 256 ];
	int serialNumberLength, endPos, length, status;
	time_t revocationTime;

	/* Determine the overall size of the entry */
	readSequence( stream, &length );
	endPos = ( int ) stell( stream ) + length;

⌨️ 快捷键说明

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