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

📄 read.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:
*																			*
****************************************************************************/

/* Read the information in a certificate */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readCertInfo( INOUT STREAM *stream, 
						 INOUT CERT_INFO *certInfoPtr )
	{
	CRYPT_ALGO_TYPE dummy;
	int length, endPos, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );

	/* Read the outer SEQUENCE and version number if it's present */
	readSequence( stream, &length );
	endPos = stell( stream ) + length;
	if( peekTag( stream ) == MAKE_CTAG( CTAG_CE_VERSION ) )
		{
		long version;

		readConstructed( stream, NULL, CTAG_CE_VERSION );
		status = readShortInteger( stream, &version );
		if( cryptStatusError( status ) )
			return( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_VERSION,
									 status ) );
		certInfoPtr->version = version + 1;	/* Zero-based */
		}
	else
		certInfoPtr->version = 1;

	/* Read the serial number and signature algorithm information.  The
	   algorithm information was included to avert a somewhat obscure attack
	   that isn't possible anyway because of the way the signature data is
	   encoded in PKCS #1 sigs (although it's still possible for some of the
	   ISO signature types) so there's no need to record it, however we 
	   record it because some higher-level protocols use the hash algorithm 
	   in the certificate as an implicit indicator of the hash algorithm 
	   that they'll use */
	status = readSerialNumber( stream, certInfoPtr, DEFAULT_TAG );
	if( cryptStatusOK( status ) )
		status = readAlgoIDext( stream, &dummy, \
								&certInfoPtr->cCertCert->hashAlgo );
	if( cryptStatusError( status ) )
		return( status );

	/* Read the issuer name, validity information, and subject name */
	status = readIssuerDN( stream, certInfoPtr );
	if( cryptStatusOK( status ) )
		status = readValidity( stream, certInfoPtr );
	if( cryptStatusOK( status ) )
		status = readSubjectDN( stream, certInfoPtr );
	if( cryptStatusError( status ) )
		return( status );

	/* Check to see whether it's a self-signed certificate */
	if( certInfoPtr->issuerDNsize == certInfoPtr->subjectDNsize && \
		!memcmp( certInfoPtr->issuerDNptr, certInfoPtr->subjectDNptr,
				 certInfoPtr->subjectDNsize ) )
		certInfoPtr->flags |= CERT_FLAG_SELFSIGNED;

	/* Read the public key information */
	status = readPublicKeyInfo( stream, certInfoPtr );
	if( cryptStatusError( status ) )
		return( status );

	/* Read the issuer and subject unique ID's if there are any present */
	if( peekTag( stream ) == MAKE_CTAG_PRIMITIVE( CTAG_CE_ISSUERUNIQUEID ) )
		{
		status = readUniqueID( stream, certInfoPtr,
							   CRYPT_CERTINFO_ISSUERUNIQUEID );
		if( cryptStatusError( status ) )
			return( status );
		}
	if( peekTag( stream ) == MAKE_CTAG_PRIMITIVE( CTAG_CE_SUBJECTUNIQUEID ) )
		{
		status = readUniqueID( stream, certInfoPtr,
							   CRYPT_CERTINFO_SUBJECTUNIQUEID );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Read the extensions if there are any present.  Because some 
	   certificates will have broken encoding of lengths we allow for a bit 
	   of slop for software that gets the length encoding wrong by a few 
	   bytes */
	if( stell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE )
		{
		status = readAttributes( stream, &certInfoPtr->attributes,
						CRYPT_CERTTYPE_CERTIFICATE, endPos - stell( stream ),
						&certInfoPtr->errorLocus, &certInfoPtr->errorType );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Fix up any problems in attributes */
	return( fixAttributes( certInfoPtr ) );
	}

/* Read the information in an attribute certificate */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readAttributeCertInfo( INOUT STREAM *stream, 
								  INOUT CERT_INFO *certInfoPtr )
	{
	int length, endPos, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );

	/* Read the outer SEQUENCE and version number */
	readSequence( stream, &length );
	endPos = stell( stream ) + length;
	if( peekTag( stream ) == BER_INTEGER )
		{
		long version;

		status = readShortInteger( stream, &version );
		if( cryptStatusError( status ) )
			return( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_VERSION,
									 status ) );
		certInfoPtr->version = version + 1;	/* Zero-based */
		}
	else
		certInfoPtr->version = 1;

	/* Read the subject and issuer names */
	if( peekTag( stream ) == MAKE_CTAG( CTAG_AC_BASECERTIFICATEID ) )
		{
		return( CRYPT_ERROR );	/* Not handled yet */
		}
	if( peekTag( stream ) == MAKE_CTAG( CTAG_AC_ENTITYNAME ) )
		{
		readConstructed( stream, NULL, CTAG_AC_ENTITYNAME );
		status = readSubjectDN( stream, certInfoPtr );
		if( cryptStatusError( status ) )
			return( status );
		}
	status = readIssuerDN( stream, certInfoPtr );
	if( cryptStatusError( status ) )
		return( status );

	/* Skip the signature algorithm information.  This was included to avert
	   a somewhat obscure attack that isn't possible anyway because of the
	   way the signature data is encoded in PKCS #1 sigs (although it's still
	   possible for some of the ISO signature types) so there's no need to 
	   record it */
	readUniversal( stream );

	/* Read the serial number and validity information */
	status = readSerialNumber( stream, certInfoPtr, DEFAULT_TAG );
	if( cryptStatusOK( status ) )
		status = readValidity( stream, certInfoPtr );
	if( cryptStatusError( status ) )
		return( status );

	/* Skip the attributes for now since these aren't really defined yet */
	readUniversal( stream );

	/* Read the issuer unique ID if there's one present */
	if( peekTag( stream ) == BER_BITSTRING )
		{
		status = readUniqueID( stream, certInfoPtr,
							   CRYPT_CERTINFO_ISSUERUNIQUEID );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Read the extensions if there are any present.  Because some 
	   certificates will have broken encoding of lengths we allow for a bit 
	   of slop for software that gets the length encoding wrong by a few 
	   bytes */
	if( stell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE )
		{
		status = readAttributes( stream, &certInfoPtr->attributes,
						CRYPT_CERTTYPE_ATTRIBUTE_CERT, endPos - stell( stream ),
						&certInfoPtr->errorLocus, &certInfoPtr->errorType );
		}

	return( status );
	}

/* Read the information in a CRL.  We read various lengths as long values
   since CRLs can get quite large */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readCRLInfo( INOUT STREAM *stream, 
						INOUT CERT_INFO *certInfoPtr )
	{
	CERT_REV_INFO *certRevInfo = certInfoPtr->cCertRev;
	long length, endPos;
	int status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );

	/* If it's a standalone CRL entry, read the single entry and return */
	if( certInfoPtr->flags & CERT_FLAG_CRLENTRY )
		{
		return( readCRLentry( stream, &certRevInfo->revocations,
							  &certInfoPtr->errorLocus,
							  &certInfoPtr->errorType ) );
		}

	/* Read the outer SEQUENCE and version number if it's present */
	status = readLongSequence( stream, &length );
	if( cryptStatusOK( status ) && length == CRYPT_UNUSED )
		{
		/* If it's an (invalid) indefinite-length encoding we can't do
		   anything with it */
		status = CRYPT_ERROR_BADDATA;
		}
	if( cryptStatusError( status ) )
		return( status );
	endPos = stell( stream ) + length;
	if( peekTag( stream ) == BER_INTEGER )
		{
		long version;

		status = readShortInteger( stream, &version );
		if( cryptStatusError( status ) )
			return( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_VERSION,
									 status ) );
		certInfoPtr->version = version + 1;	/* Zero-based */
		}
	else
		certInfoPtr->version = 1;

	/* Skip the signature algorithm information.  This was included to avert
	   a somewhat obscure attack that isn't possible anyway because of the
	   way the signature data is encoded in PKCS #1 sigs (although it's still
	   possible for some of the ISO signature types) so there's no need to 
	   record it */
	readUniversal( stream );

	/* Read the issuer name, update time, and optional next update time */
	status = readIssuerDN( stream, certInfoPtr );
	if( cryptStatusError( status ) )
		return( status );
	status = readUTCTime( stream, &certInfoPtr->startTime );
	if( cryptStatusError( status ) )
		return( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_THISUPDATE,
								 status ) );
	if( peekTag( stream ) == BER_TIME_UTC )
		{
		status = readUTCTime( stream, &certInfoPtr->endTime );
		if( cryptStatusError( status ) )
			return( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_NEXTUPDATE,
									 status ) );
		}

	/* Read the SEQUENCE OF revoked certificates and make the currently 
	   selected one the start of the list */
	if( stell( stream ) < endPos - MIN_ATTRIBUTE_SIZE && \
		peekTag( stream ) == BER_SEQUENCE )
		{
		/* The following loop is a bit tricky to failsafe because it is
		   actualy possible to encounter 100MB CRLs, which the failsafe
		   would otherwise identify as an error.  Because CRLs can range so
		   far outside what would be considered a sane value we can't
		   really bound the loop in any way */
		status = readLongSequence( stream, &length );
		if( cryptStatusOK( status ) && length == CRYPT_UNUSED )
			{
			/* If it's an (invalid) indefinite-length encoding we can't do
			   anything with it */
			status = CRYPT_ERROR_BADDATA;
			}
		while( cryptStatusOK( status ) && length > MIN_ATTRIBUTE_SIZE )
			{
			const long innerStartPos = stell( stream );

			status = readCRLentry( stream, &certRevInfo->revocations,
								   &certInfoPtr->errorLocus,
								   &certInfoPtr->errorType );
			length -= stell( stream ) - innerStartPos;
			}
		if( cryptStatusError( status ) )
			{
			/* The invalid attribute isn't quite a user certificate, but
			   it's the data that arose from a user certificate so it's the
			   most appropriate locus for the error */
			return( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
									 status ) );
			}
		certRevInfo->currentRevocation = certRevInfo->revocations;
		}

	/* Read the extensions if there are any present.  Because some CRL's 
	   will have broken encoding of lengths we allow for a bit of slop for 
	   software that gets the length encoding wrong by a few bytes */
	if( stell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE )
		{
		status = readAttributes( stream, &certInfoPtr->attributes,
						CRYPT_CERTTYPE_CRL, endPos - stell( stream ),
						&certInfoPtr->errorLocus, &certInfoPtr->errorType );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Fix up any problems in attributes */
	return( fixAttributes( certInfoPtr ) );
	}

/* Read CMS attributes */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readCmsAttributes( INOUT STREAM *stream, 
							  INOUT CERT_INFO *attributeInfoPtr )
	{
	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( attributeInfoPtr, sizeof( CERT_INFO ) ) );

	/* CMS attributes are straight attribute objects so we just pass the call
	   through.  In addition since there's no encapsulation we specify a
	   special-case length of 0 to mean "whatever's there" */
	return( readAttributes( stream, &attributeInfoPtr->attributes,
							CRYPT_CERTTYPE_CMS_ATTRIBUTES, 0,
							&attributeInfoPtr->errorLocus,
							&attributeInfoPtr->errorType ) );
	}

/* Read the information in a certification request */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readCertRequestInfo( INOUT STREAM *stream, 
								INOUT CERT_INFO *certInfoPtr )
	{
	long version;
	int status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );

⌨️ 快捷键说明

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