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

📄 certrev.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
		newElement->attributes = NULL;
		newElement->next = NULL;

		/* Set the status to 'unknown' by default, this means that any
		   entries that 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( *destListHeadPtrPtr == NULL )
			*destListHeadPtrPtr = destListCursor = newElement;
		else
			{
			destListCursor->next = newElement;
			destListCursor = newElement;
			}
		}
	ENSURES( iterationCount < FAILSAFE_ITERATIONS_MAX );

	return( CRYPT_OK );
	}

/* Prepare the entries in a revocation list prior to encoding them */

CHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5, 6 ) ) \
int prepareRevocationEntries( INOUT_OPT REVOCATION_INFO *listPtr, 
							  const time_t defaultTime,
							  OUT_PTR REVOCATION_INFO **errorEntry,
							  const BOOLEAN isSingleEntry,
							  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
								CRYPT_ATTRIBUTE_TYPE *errorLocus,
							  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
								CRYPT_ERRTYPE_TYPE *errorType )
	{
	REVOCATION_INFO *revocationEntry;
	const time_t currentTime = ( defaultTime > MIN_TIME_VALUE ) ? \
							   defaultTime : getApproxTime();
	int iterationCount, status;

	assert( listPtr == NULL || \
			isReadPtr( listPtr, sizeof( REVOCATION_INFO ) ) );
	assert( isWritePtr( errorEntry, sizeof( REVOCATION_INFO * ) ) );
	assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
	assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );

	/* Clear return value */
	*errorEntry = NULL;

	/* If the revocation list is empty there's nothing to do */
	if( listPtr == NULL )
		return( CRYPT_OK );

	/* Set the revocation time if this hasn't already been set.  If there's a
	   default time set we use that otherwise we use the current time */
	for( revocationEntry = listPtr, iterationCount = 0; 
		 revocationEntry != NULL && iterationCount < FAILSAFE_ITERATIONS_LARGE;
		 revocationEntry = revocationEntry->next, iterationCount++ )
		{
		const ATTRIBUTE_LIST *attributeListPtr;

		if( revocationEntry->revocationTime <= MIN_TIME_VALUE )
			revocationEntry->revocationTime = currentTime;

		/* Check whether the certificate was revoked with a reason of 
		   neverValid, which requires special handling of dates because 
		   X.509 doesn't formally define a neverValid reason, assuming that 
		   all CAs are perfect and never issue certificates in error.  The 
		   general idea is to set the two to the same value with the 
		   invalidity date (which should be earlier than the revocation date, 
		   at least in a sanely-run CA) taking precedence.  A revocation 
		   with this reason code will in general only be issued by the 
		   cryptlib CA (where it's required to handle problems in the CMP 
		   protocol) and this always sets the invalidity date so in almost 
		   all cases we'll be setting the revocation date to the 
		   (CA-specified) invalidity date which is the date of issue of the 
		   certificate being revoked */
		attributeListPtr = findAttributeField( revocationEntry->attributes,
											   CRYPT_CERTINFO_CRLREASON,
											   CRYPT_ATTRIBUTE_NONE );
		if( attributeListPtr != NULL && \
			attributeListPtr->intValue == CRYPT_CRLREASON_NEVERVALID )
			{
			/* The certificate was revoked with the neverValid code, see if 
			   there's an invalidity date present */
			attributeListPtr = \
					findAttributeField( revocationEntry->attributes,
										CRYPT_CERTINFO_INVALIDITYDATE,
										CRYPT_ATTRIBUTE_NONE );
			if( attributeListPtr == NULL )
				{
				/* There's no invalidity date present, set it to the same as
				   the revocation date */
				status = addAttributeField( &revocationEntry->attributes,
											CRYPT_CERTINFO_INVALIDITYDATE,
											CRYPT_ATTRIBUTE_NONE,
											&revocationEntry->revocationTime,
											sizeof( time_t ), ATTR_FLAG_NONE,
											errorLocus, errorType );
				if( cryptStatusError( status ) )
					{
					/* Remember the entry that caused the problem */
					*errorEntry = revocationEntry;
					return( status );
					}
				}
			else
				{
				/* There's an invalidity date present, make sure the
				   revocation date is the same as the invalidity date */
				revocationEntry->revocationTime = \
						*( time_t * ) attributeListPtr->value;
				}
			}

		/* If we're only processing a single CRL entry rather than an 
		   entire revocation list we're done */
		if( isSingleEntry )
			break;
		}
	ENSURES( iterationCount < FAILSAFE_ITERATIONS_MAX );

	/* Check the attributes for each entry in a revocation list */
	for( revocationEntry = listPtr, iterationCount = 0; 
		 revocationEntry != NULL && iterationCount < FAILSAFE_ITERATIONS_MAX; 
		 revocationEntry = revocationEntry->next, iterationCount++ )
		{
		if( revocationEntry->attributes != NULL )
			{
			status = checkAttributes( ATTRIBUTE_CERTIFICATE,
									  revocationEntry->attributes,
									  errorLocus, errorType );
			if( cryptStatusError( status ) )
				{
				/* Remember the entry that caused the problem */
				*errorEntry = revocationEntry;
				return( status );
				}
			}

		/* If we're only processing a single CRL entry rather than an 
		   entire revocation list we're done */
		if( isSingleEntry )
			break;
		}
	ENSURES( iterationCount < FAILSAFE_ITERATIONS_MAX );

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							Read/write CRL Information						*
*																			*
****************************************************************************/

/* Read/write CRL entries:

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

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int sizeofCRLentry( INOUT REVOCATION_INFO *crlEntry )
	{
	assert( isWritePtr( crlEntry, sizeof( REVOCATION_INFO ) ) );

	/* Remember the encoded attribute size for later when we write the
	   attributes */
	crlEntry->attributeSize = sizeofAttributes( crlEntry->attributes );

	return( ( int ) sizeofObject( \
						sizeofInteger( crlEntry->id, crlEntry->idLength ) + \
						sizeofUTCTime() + \
						( ( crlEntry->attributeSize > 0 ) ? \
							( int ) sizeofObject( crlEntry->attributeSize ) : 0 ) ) );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \
int readCRLentry( INOUT STREAM *stream, 
				  INOUT_PTR REVOCATION_INFO **listHeadPtrPtr,
				  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \
					CRYPT_ATTRIBUTE_TYPE *errorLocus,
				  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \
					CRYPT_ERRTYPE_TYPE *errorType )
	{
	REVOCATION_INFO *currentEntry;
	BYTE serialNumber[ MAX_SERIALNO_SIZE + 8 ];
	int serialNumberLength, endPos, length, status;
	time_t revocationTime;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( listHeadPtrPtr, sizeof( REVOCATION_INFO * ) ) );
	assert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );
	assert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );

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

	/* Read the integer component of the serial number (limited to a sane
	   length) and the revocation time */
	readInteger( stream, serialNumber, MAX_SERIALNO_SIZE,
				 &serialNumberLength );
	status = readUTCTime( stream, &revocationTime );
	if( cryptStatusError( status ) )
		return( status );

	/* Add the entry to the revocation information list.  The ID type isn't
	   quite an issueAndSerialNumber but the checking code eventually
	   converts it into this form using the supplied issuer certificate DN */
	status = addRevocationEntry( listHeadPtrPtr, &currentEntry,
								 CRYPT_IKEYID_ISSUERANDSERIALNUMBER,
								 serialNumber, serialNumberLength,
								 ( endPos > CRL_SORT_LIMIT ) ? TRUE : FALSE );
	if( cryptStatusError( status ) )
		return( status );
	currentEntry->revocationTime = revocationTime;

	/* Read the extensions if there are any present.  Since these are per-
	   entry extensions we read the extensions themselves as
	   CRYPT_CERTTYPE_NONE rather than CRYPT_CERTTYPE_CRL to make sure
	   that they're processed as required */
	if( stell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE )
		{
		status = readAttributes( stream, &currentEntry->attributes,
								 CRYPT_CERTTYPE_NONE, length,
								 errorLocus, errorType );
		}

	return( status );
	}

STDC_NONNULL_ARG( ( 1, 2 ) ) \
int writeCRLentry( INOUT STREAM *stream, 
				   const REVOCATION_INFO *crlEntry )
	{
	const int revocationLength = \
				sizeofInteger( crlEntry->id, crlEntry->idLength ) + \
				sizeofUTCTime() + \
				( ( crlEntry->attributeSize > 0 ) ? \
					( int ) sizeofObject( crlEntry->attributeSize ) : 0 );
	int status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isReadPtr( crlEntry, sizeof( REVOCATION_INFO ) ) );

	/* Write the CRL entry */
	writeSequence( stream, revocationLength );
	writeInteger( stream, crlEntry->id, crlEntry->idLength, DEFAULT_TAG );
	status = writeUTCTime( stream, crlEntry->revocationTime, DEFAULT_TAG );
	if( cryptStatusError( status ) || crlEntry->attributeSize <= 0 )
		return( status );

	/* Write the per-entry extensions.  Since these are per-entry extensions
	   we write them as CRYPT_CERTTYPE_NONE rather than CRYPT_CERTTYPE_CRL to
	   make sure that they're processed as required  */
	return( writeAttributes( stream, crlEntry->attributes,
							 CRYPT_CERTTYPE_NONE, crlEntry->attributeSize ) );
	}

/****************************************************************************
*																			*
*							Read/write OCSP Information						*
*																			*
****************************************************************************/

/* Read/write an OCSP certificate ID:

	CertID ::=	CHOICE {
		certID			SEQUENCE {
			hashAlgo	AlgorithmIdentifier,
			iNameHash	OCTET STRING,	-- Hash of issuerName
			iKeyHash	OCTET STRING,	-- Hash of issuer SPKI w/o tag+len
			serialNo	INTEGER
				},
		certificate	[0]	EXPLICIT [0] EXPLICIT Certificate,
		certIdWithSignature
					[1]	EXPLICIT SEQUENCE {
			iAndS		IssuerAndSerialNumber,
			tbsCertHash	BIT STRING,
			certSig		SEQUENCE {
				sigAlgo	AlgorithmIdentifier,
				sigVal	BIT STRING
				}
			}
		} */

CHECK_RETVAL_RANGE( MAX_ERROR, 1024 ) STDC_NONNULL_ARG( ( 1 ) ) \
static int sizeofOcspID( const REVOCATION_INFO *ocspEntry )
	{
	assert( isReadPtr( ocspEntry, sizeof( REVOCATION_INFO ) ) );
	
	REQUIRES( ocspEntry->idType == CRYPT_KEYID_NONE );

	/* For now we don't try and handle anything except the v1 ID since the
	   status of v2 is uncertain (it doesn't add anything to v1 except even
	   more broken IDs) */
	return( ocspEntry->idLength );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \
static int readOcspID( INOUT STREAM *stream, 
					   OUT_ENUM_OPT( CRYPT_KEYID ) CRYPT_KEYID_TYPE *idType,
					   OUT_BUFFER( idMaxLen, *idLen ) BYTE *id, 
					   IN_LENGTH_SHORT_MIN( 16 ) const int idMaxLen,
					   OUT_LENGTH_SHORT_Z int *idLen )
	{
	HASHFUNCTION_ATOMIC hashFunctionAtomic;
	void *dataPtr = DUMMY_INIT_PTR;
	int length, tag, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( idType, sizeof( CRYPT_KEYID_TYPE ) ) );
	assert( isWritePtr( id, idMaxLen ) );
	assert( isWritePtr( idLen, sizeof( int ) ) );

	REQUIRES( idMaxLen >= 16 && idMaxLen < MAX_INTLENGTH_SHORT );

	getHashAtomicParameters( CRYPT_ALGO_SHA1, &hashFunctionAtomic, NULL );

	/* Clear return values */
	*idType = CRYPT_KEYID_NONE;
	memset( id, 0, min( 16, idMaxLen ) );
	*idLen = 0;

	/* Read the ID */
	tag = peekTag( stream );
	if( cryptStatusError( tag ) )
		return( tag );
	switch( tag )
		{
		case BER_SEQUENCE:
			/* We can't really do anything with v1 IDs since the one-way
			   hashing process destroys any chance of being able to work
			   with them and the fact that no useful certificate info is 
			   hashed means that we can't use them to identify a cert.  As 
			   a result the following ID type will always produce a result
			   of "unknown" */
			*idType = CRYPT_KEYID_NONE;
			status = getStreamObjectLength( stream, &length );
			if( cryptStatusError( status ) )
				return( status );
			if( length < 8 )
				return( CRYPT_ERROR_UNDERFLOW );
			if( length > idMaxLen )
				return( CRYPT_ERROR_OVERFLOW );
			*idLen = length;
			return( sread( stream, id, length ) );

		case MAKE_CTAG( CTAG_OI_CERTIFICATE ):
			/* Convert the certificate to a certID */
			*idType = CRYPT_IKEYID_CERTID;
			*idLen = KEYID_SIZE;
			readConstructed( stream, NULL, CTAG_OI_CERTIFICATE );
			status = readConstructed( stream, &length, 0 );
			if( cryptStatusOK( status ) )
				status = sMemGetDataBlock( stream, &dataPtr, length );
			if( cryptStatusError( status ) )
				return( status );
			hashFunctionAtomic( id, KEYID_SIZE, dataPtr, length );
			return( readUniversal( stream ) );

		case MAKE_CTAG( CTAG_OI_CERTIDWITHSIG ):
			/* A bizarro ID dreamed up by Denis Pinkas that manages to carry
			   over all the problems of the v1 ID without being compatible
			   with it.  It's almost as unworkable as the v1 original but we 

⌨️ 快捷键说明

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