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

📄 certrev.c

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

	/* 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 );
	}

int writeCRLentry( STREAM *stream, const REVOCATION_INFO *crlEntry )
	{
	const int revocationLength = \
				sizeofInteger( crlEntry->data, crlEntry->dataLength ) + \
				sizeofUTCTime() + \
				( ( crlEntry->attributeSize > 0 ) ? \
					( int ) sizeofObject( crlEntry->attributeSize ) : 0 );
	int status;

	assert( isReadPtr( crlEntry, sizeof( REVOCATION_INFO ) ) );

	/* Write the CRL entry */
	writeSequence( stream, revocationLength );
	writeInteger( stream, crlEntry->data, crlEntry->dataLength, 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 cert 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
				}
			}
		} */

static int sizeofOcspID( const REVOCATION_INFO *ocspEntry )
	{
	assert( isReadPtr( ocspEntry, sizeof( REVOCATION_INFO ) ) );
	assert( ocspEntry->type == 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->dataLength );
	}

static int readOcspID( STREAM *stream, CRYPT_KEYID_TYPE *idType, 
					   BYTE *idBuffer, int *idLen, const int idMaxLen )
	{
	HASHFUNCTION hashFunction;
	int length, status;

	getHashParameters( CRYPT_ALGO_SHA, &hashFunction, NULL );

	*idType = CRYPT_KEYID_NONE;
	*idLen = 0;
	switch( peekTag( stream ) )
		{
		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 cert 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;
			length = getStreamObjectLength( stream );
			if( cryptStatusError( length ) )
				return( length );
			if( length > idMaxLen )
				return( CRYPT_ERROR_OVERFLOW );
			*idLen = length;
			return( sread( stream, idBuffer, length ) );

		case MAKE_CTAG( CTAG_OI_CERTIFICATE ):
			/* Convert the cert to a certID */
			*idType = CRYPT_IKEYID_CERTID;
			*idLen = KEYID_SIZE;
			readConstructed( stream, NULL, CTAG_OI_CERTIFICATE );
			status = readConstructed( stream, &length, 0 );
			if( cryptStatusError( status ) )
				return( status );
			hashFunction( NULL, idBuffer, sMemBufPtr( stream ), length, 
						  HASH_ALL );
			return( readUniversal( stream ) );
		
		case MAKE_CTAG( CTAG_OI_CERTIDWITHSIG ):
			{
			void *iAndSPtr;

			/* 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 can convert the iAndS to an issuerID and use that */
			*idType = CRYPT_IKEYID_ISSUERID;
			*idLen = KEYID_SIZE;
			readConstructed( stream, NULL, CTAG_OI_CERTIDWITHSIG );
			readSequence( stream, NULL );
			iAndSPtr = sMemBufPtr( stream );
			status = readSequence( stream, &length );
			if( cryptStatusError( status ) )
				return( status );
			hashFunction( NULL, idBuffer, iAndSPtr, sizeofObject( length ), 
						  HASH_ALL );
			sSkip( stream, length );			/* issuerAndSerialNumber */
			readUniversal( stream );			/* tbsCertificateHash */
			return( readUniversal( stream ) );	/* certSignature */
			}
		}

	return( CRYPT_ERROR_BADDATA );
	}

static int writeOcspID( STREAM *stream, const REVOCATION_INFO *ocspEntry )
	{
	return( swrite( stream, ocspEntry->data, ocspEntry->dataLength ) );
	}

/* Read/write an OCSP request entry:

	Entry ::= SEQUENCE {				-- Request
		certID			CertID,
		extensions	[0]	EXPLICIT Extensions OPTIONAL
		} */

int sizeofOcspRequestEntry( REVOCATION_INFO *ocspEntry )
	{
	assert( isWritePtr( ocspEntry, sizeof( REVOCATION_INFO ) ) );
	assert( ocspEntry->type == CRYPT_KEYID_NONE );

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

	return( ( int ) \
			sizeofObject( sizeofOcspID( ocspEntry ) + \
						  ( ( ocspEntry->attributeSize ) ? \
							( int ) sizeofObject( ocspEntry->attributeSize ) : 0 ) ) );
	}

int readOcspRequestEntry( STREAM *stream, REVOCATION_INFO **listHeadPtr,
						  CERT_INFO *certInfoPtr )
	{
	REVOCATION_INFO *currentEntry;
	BYTE idBuffer[ MAX_ID_SIZE ];
	CRYPT_KEYID_TYPE idType;
	int endPos, length, status;

	assert( isWritePtr( listHeadPtr, sizeof( REVOCATION_INFO * ) ) );
	assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );

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

	/* Read the ID information */
	status = readOcspID( stream, &idType, idBuffer, &length, MAX_ID_SIZE );
	if( cryptStatusError( status ) )
		return( status );

	/* Add the entry to the revocation information list */
	status = addRevocationEntry( listHeadPtr, &currentEntry, idType, 
								 idBuffer, length, FALSE );
	if( cryptStatusError( status ) || \
		stell( stream ) > endPos - MIN_ATTRIBUTE_SIZE )
		return( status );

	/* Read the extensions.  Since these are per-entry extensions we read 
	   the wrapper here and read the extensions themselves as 
	   CRYPT_CERTTYPE_NONE rather than CRYPT_CERTTYPE_OCSP to make sure that 
	   they're processed as required */
	status = readConstructed( stream, &length, CTAG_OR_EXTENSIONS );
	if( cryptStatusError( status ) )
		return( status );
	return( readAttributes( stream, &currentEntry->attributes,
							CRYPT_CERTTYPE_NONE, length,
							&certInfoPtr->errorLocus, 
							&certInfoPtr->errorType ) );
	}

int writeOcspRequestEntry( STREAM *stream, const REVOCATION_INFO *ocspEntry )
	{
	const int attributeSize = ( ocspEntry->attributeSize ) ? \
					( int ) sizeofObject( ocspEntry->attributeSize ) : 0;
	int status;

	assert( isReadPtr( ocspEntry, sizeof( REVOCATION_INFO ) ) );

	/* Write the header and ID information */
	writeSequence( stream, sizeofOcspID( ocspEntry ) + attributeSize );
	status = writeOcspID( stream, ocspEntry );
	if( cryptStatusError( status ) || ocspEntry->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_OCSP 
	   to make sure that they're processed as required */
	return( writeAttributes( stream, ocspEntry->attributes, 
							 CRYPT_CERTTYPE_NONE, ocspEntry->attributeSize ) );
	}

/* Read/write an OCSP response entry:

	Entry ::= SEQUENCE {
		certID			CertID,
		certStatus		CHOICE {
			notRevd	[0]	IMPLICIT NULL,
			revd	[1]	SEQUENCE {
				revTime	GeneralizedTime, 
				revReas	[0] EXPLICIT CRLReason Optional
							},
			unknown	[2] IMPLICIT NULL 
						}, 
		thisUpdate		GeneralizedTime, 
		extensions	[1]	EXPLICIT Extensions OPTIONAL 
		} */

int sizeofOcspResponseEntry( REVOCATION_INFO *ocspEntry )
	{
	int certStatusSize = 0;

	assert( isWritePtr( ocspEntry, sizeof( REVOCATION_INFO ) ) );

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

	/* Determine the size of the cert status field */
	certStatusSize = ( ocspEntry->status != CRYPT_OCSPSTATUS_REVOKED ) ? \
					 sizeofNull() : ( int ) sizeofObject( sizeofGeneralizedTime() );

	return( ( int ) \
			sizeofObject( sizeofOcspID( ocspEntry ) + \
						  certStatusSize + sizeofGeneralizedTime() ) + \
						  ( ( ocspEntry->attributeSize ) ? \
							( int ) sizeofObject( ocspEntry->attributeSize ) : 0 ) );
	}

int readOcspResponseEntry( STREAM *stream, REVOCATION_INFO **listHeadPtr,
						   CERT_INFO *certInfoPtr )
	{
	REVOCATION_INFO *currentEntry;
	BYTE idBuffer[ MAX_ID_SIZE ];
	CRYPT_KEYID_TYPE idType;
	int endPos, length, crlReason = 0, status;

	assert( isWritePtr( listHeadPtr, sizeof( REVOCATION_INFO * ) ) );
	assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );

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

	/* Read the ID information */
	status = readOcspID( stream, &idType, idBuffer, &length, MAX_ID_SIZE );
	if( cryptStatusError( status ) )
		return( status );

	/* Add the entry to the revocation information list */
	status = addRevocationEntry( listHeadPtr, &currentEntry, idType, 
								 idBuffer, length, FALSE );
	if( cryptStatusError( status ) )
		return( status );

	/* Read the status information */
	switch( peekTag( stream ) )
		{
		case MAKE_CTAG_PRIMITIVE( OCSP_STATUS_NOTREVOKED ):
			currentEntry->status = CRYPT_OCSPSTATUS_NOTREVOKED;
			readUniversal( stream );
			break;

		case MAKE_CTAG( OCSP_STATUS_REVOKED ):
			currentEntry->status = CRYPT_OCSPSTATUS_REVOKED;
			readConstructed( stream, NULL, OCSP_STATUS_REVOKED );
			readGeneralizedTime( stream, &currentEntry->revocationTime );
			if( peekTag( stream ) == MAKE_CTAG( 0 ) )
				{
				/* Remember the crlReason for later */
				readConstructed( stream, NULL, 0 );
				readEnumerated( stream, &crlReason );
				}
			break;

		case MAKE_CTAG_PRIMITIVE( OCSP_STATUS_UNKNOWN ):
			currentEntry->status = CRYPT_OCSPSTATUS_UNKNOWN;
			readUniversal( stream );
			break;

		default:
			return( CRYPT_ERROR_BADDATA );
		}
	status = readGeneralizedTime( stream, &certInfoPtr->startTime );
	if( cryptStatusOK( status ) && peekTag( stream ) == MAKE_CTAG( 0 ) )
		{
		readConstructed( stream, NULL, 0 );
		status = readGeneralizedTime( stream, &certInfoPtr->endTime );
		}
	if( cryptStatusError( status ) )
		return( status );

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

	/* If there's a crlReason present in the response and none as an 
	   extension, add it as an extension (OCSP allows the same information 
	   to be specified in two different places, to make it easier we always 
	   return it as a crlReason extension, however some implementations 
	   return it in both places so we have to make sure that we don't try and 
	   add it a second time) */
	if( findAttributeField( currentEntry->attributes, 
							CRYPT_CERTINFO_CRLREASON, 
							CRYPT_ATTRIBUTE_NONE ) == NULL )
		status = addAttributeField( &currentEntry->attributes,
						CRYPT_CERTINFO_CRLREASON, CRYPT_ATTRIBUTE_NONE, 
						&crlReason, CRYPT_UNUSED, ATTR_FLAG_NONE, 
						&certInfoPtr->errorLocus, &certInfoPtr->errorType );

	return( status );
	}

int writeOcspResponseEntry( STREAM *stream, const REVOCATION_INFO *ocspEntry,
							const time_t entryTime )
	{
	int certStatusSize, status;

	assert( isReadPtr( ocspEntry, sizeof( REVOCATION_INFO ) ) );

	/* Determine the size of the cert status field */
	certStatusSize = ( ocspEntry->status != CRYPT_OCSPSTATUS_REVOKED ) ? \
					 sizeofNull() : ( int ) sizeofObject( sizeofGeneralizedTime() );

	/* Write the header and ID information */
	writeSequence( stream, sizeofOcspID( ocspEntry ) + \
				   certStatusSize + sizeofGeneralizedTime() + \
				   ( ( ocspEntry->attributeSize ) ? \
						( int ) sizeofObject( ocspEntry->attributeSize ) : 0 ) );
	writeOcspID( stream, ocspEntry );

	/* Write the cert status */
	if( ocspEntry->status == CRYPT_OCSPSTATUS_REVOKED )
		{
		writeConstructed( stream, sizeofGeneralizedTime(), 
						  CRYPT_OCSPSTATUS_REVOKED );
		writeGeneralizedTime( stream, ocspEntry->revocationTime, 
							  DEFAULT_TAG );
		}
	else
		/* An other-than-revoked status is communicated as a tagged NULL 
		   value.  For no known reason this portion of OCSP uses implicit
		   tagging, since it's the one part of the PDU in which an
		   explicit tag would actually make sense */
		writeNull( stream, ocspEntry->status );

	/* Write the current update time, which should be the current time. 
	   Since new status information is always available, we don't write a 
	   nextUpdate time (in fact there is some disagreement over whether these
	   times are based on CRL info, responder info, the response dispatch
	   time, or a mixture of the above, implementations can be found that
	   return all manner of peculiar values here) */
	status = writeGeneralizedTime( stream, entryTime, DEFAULT_TAG );
	if( cryptStatusError( status ) || ocspEntry->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_OCSP 
	   to make sure that they're processed as required */
	return( writeAttributes( stream, ocspEntry->attributes, 
							 CRYPT_CERTTYPE_NONE, ocspEntry->attributeSize ) );
	}

⌨️ 快捷键说明

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