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

📄 imp_exp.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:
			*offset = stell( stream );
			status = readSequence( stream, NULL );
			return( cryptStatusError( status ) ? \
					status : CRYPT_CERTTYPE_NONE );
			}
		else
			{
			if( memcmp( oid, OID_NS_CERTSEQ, oidLength ) )
				return( CRYPT_ERROR_BADDATA );
			}
		}
	readConstructedI( stream, NULL, 0 );
	status = readSequenceI( stream, NULL );
	if( cryptStatusError( status ) )
		return( status );

	/* If it's a PKCS #7 certificate chain, burrow into the inner PKCS #7
	   content */
	if( isCertChain )
		{
		long integer;
		int value = DUMMY_INIT, innerLength;

		/* Read the version number (1 = PKCS #7 v1.5, 2 = PKCS #7 v1.6,
		   3 = S/MIME with attribute certificate(s)) and SET OF
		   DigestAlgorithmIdentifier (this is empty for a pure certificate 
		   chain, nonempty for signed data) */
		status = readShortInteger( stream, &integer );
		if( cryptStatusOK( status ) && ( integer < 1 || integer > 3 ) )
			status = CRYPT_ERROR_BADDATA;
		if( cryptStatusOK( status ) )
			status = readSet( stream, &value );
		if( cryptStatusError( status ) )
			return( status );
		if( value > 0 )
			sSkip( stream, value );

		/* Read the ContentInfo header, contentType OID (ignored) and the 
		   inner content encapsulation.  Sometimes we may (incorrectly) get 
		   passed actual signed data (rather than degenerate zero-length 
		   data signifying a pure certificate chain) so if there's data 
		   present we skip it */
		readSequenceI( stream, &innerLength );
		status = readEncodedOID( stream, oid, MAX_OID_SIZE, &oidLength, 
								 BER_OBJECT_IDENTIFIER );
		if( cryptStatusError( status ) )
			return( status );
		if( innerLength == CRYPT_UNUSED )
			{
			/* It's an indefinite-length ContentInfo, check for the EOC */
			checkEOC( stream );
			}
		else
			{
			/* If we've been fed signed data (i.e. the ContentInfo has the 
			   content field present), skip the content to get to the 
			   certificate chain */
			if( innerLength > sizeofObject( oidLength ) )
				readUniversal( stream );
			}
		status = readConstructedI( stream, NULL, 0 );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* We've finally reached the certificate(s), retry the read of the
	   certificate start */
	status = readSequence( stream, NULL );
	return( cryptStatusError( status ) ? status : CRYPT_CERTTYPE_CERTCHAIN );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 5 ) ) \
static int getCertObjectInfo( IN_BUFFER( objectTotalLength ) const void *object,
							  IN_LENGTH const int objectTotalLength,
							  OUT_LENGTH_SHORT_Z int *objectOffset, 
							  OUT_LENGTH_Z int *objectLength, 
							  OUT_ENUM_OPT( CRYPT_CERTTYPE ) \
								CRYPT_CERTTYPE_TYPE *objectType,
							  IN_ENUM( CRYPT_CERTTYPE ) \
								const CRYPT_CERTTYPE_TYPE formatHint )
	{
	STREAM stream;
	BOOLEAN isContextTagged = FALSE, isLongData = FALSE;
	int tag, length, status;

	assert( isReadPtr( object, objectTotalLength ) );
	assert( isWritePtr( objectOffset, sizeof( int ) ) );
	assert( isWritePtr( objectLength, sizeof( int ) ) );
	assert( isWritePtr( objectType, sizeof( CRYPT_CERTTYPE_TYPE ) ) );

	REQUIRES( formatHint >= CRYPT_CERTTYPE_NONE && \
			  formatHint < CRYPT_CERTTYPE_LAST );

	/* Clear return values */
	*objectOffset = *objectLength = 0;
	*objectType = CRYPT_CERTTYPE_NONE;

	/* If it's an SSL certificate chain there's no recognisable tagging, 
	   however the caller will have told us what it is */
	if( formatHint == CRYPT_ICERTTYPE_SSL_CERTCHAIN )
		{
		*objectLength = objectTotalLength;
		*objectType = CRYPT_ICERTTYPE_SSL_CERTCHAIN;
		return( CRYPT_OK );
		}

	sMemConnect( &stream, object, objectTotalLength );

	/* Check that the start of the object is in order and get its length */
	if( peekTag( &stream ) == MAKE_CTAG( 0 ) || \
		formatHint == CRYPT_ICERTTYPE_CMS_CERTSET )
		isContextTagged = TRUE;
	status = readConstructedI( &stream, &length, \
							   isContextTagged ? 0 : DEFAULT_TAG );
	if( cryptStatusError( status ) )
		{
		long longLength;

#if INT_MAX > 32767
		if( status != CRYPT_ERROR_OVERFLOW )
#endif /* Non-16-bit systems */
			{
			sMemDisconnect( &stream );
			return( status );
			}

#if INT_MAX > 32767
		ENSURES( status == CRYPT_ERROR_OVERFLOW );

		/* CRLs can grow without bounds as more and more certificates are 
		   accumulated, to handle these we have to fall back to an 
		   unconstrained read if a standard constrained read fails */
		sClearError( &stream );
		sseek( &stream, 0 );
		status = readLongSequence( &stream, &longLength );
		if( cryptStatusOK( status ) )
			{
			/* We don't have to check for the CRYPT_UNUSED indefinite-length 
			   return value in this case since we can only get here if the 
			   length overflows a 16-bit int so it can never be indefinite-
			   length */
			length = ( int ) longLength;
			isLongData = TRUE;
			}
#endif /* Non-16-bit systems */
		}
	ENSURES( cryptStatusOK( status ) );
	if( length != CRYPT_UNUSED )
		{
		/* It's a definite-length object, adjust the length for the size of 
		   the header that we read */
		length += stell( &stream );
		}
	else
		{
		/* It's a indefinite-length object, burrow into it to find it's 
		   actual length */
		status = getObjectLength( object, objectTotalLength, &length );
#if INT_MAX > 32767
		if( status == CRYPT_ERROR_OVERFLOW )
			{
			long longLength;

			status = getLongObjectLength( object, objectTotalLength, 
										  &longLength );
			if( cryptStatusOK( status ) )
				length = longLength;
			}
#endif /* Non-16-bit systems */
		}
	if( cryptStatusOK( status ) && \
		( length < 1 || length > objectTotalLength ) )
		{
		assert( DEBUG_WARN );
		status = CRYPT_ERROR_BADDATA;
		}
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( &stream );
		return( status );
		}
	*objectLength = length;

	/* If the caller has specified that the data is in a fixed format, don't 
	   try and recognise any other format.  This prevents security holes of 
	   the type common in Windows software where data purportedly of type A 
	   is auto-recognised as harmful type B and processed as such after being
	   passed as type A by security-checking code */
	if( formatHint != CRYPT_CERTTYPE_NONE )
		{
		sMemDisconnect( &stream );

		switch( formatHint )
			{
			case CRYPT_ICERTTYPE_DATAONLY:
				/* Standard certificate but created without creating a 
				   context for the accompanying public key */
				*objectType = CRYPT_CERTTYPE_CERTIFICATE;
				break;

			case CRYPT_ICERTTYPE_CTL:
				/* Certificate chain used as a container for trusted 
				   certificates, effectively a chain of 
				   CRYPT_ICERTTYPE_DATAONLY certificates */
				*objectType = CRYPT_CERTTYPE_CERTCHAIN;
				break;

			case CRYPT_ICERTTYPE_REVINFO:
				/* Single CRL entry, treated as standard CRL with portions 
				   missing */
				*objectType = CRYPT_CERTTYPE_CRL;
				break;

			default:
				*objectType = formatHint;
			}
										
		return( isLongData ? CRYPT_ERROR_OVERFLOW : CRYPT_OK );
		}

	/* First we check for the easy ones, CMS attributes, which begin with a 
	   [0] IMPLICIT SET */
	if( isContextTagged )
		{
		*objectType = CRYPT_CERTTYPE_CMS_ATTRIBUTES;
		sMemDisconnect( &stream );
		return( isLongData ? CRYPT_ERROR_OVERFLOW : CRYPT_OK );
		}

	/* If it's a PKCS #7 certificate chain or Netscape certificate sequence, 
	   there'll be an object identifier present.  Some sources also wrap
	   certificates up in oddball OID's, so we check for these as well */
	if( peekTag( &stream ) == BER_OBJECT_IDENTIFIER )
		{
		status = decodeCertWrapper( &stream, objectOffset );
		sMemDisconnect( &stream );
		if( cryptStatusError( status ) )
			return( status );
		*objectType = ( status != CRYPT_CERTTYPE_NONE ) ? \
					  status : CRYPT_CERTTYPE_CERTIFICATE;
		return( isLongData ? CRYPT_ERROR_OVERFLOW : CRYPT_OK );
		}

	/* If it's a PKCS #12 mess, there'll be a version number, 3, present */
	if( peekTag( &stream ) == BER_INTEGER )
		{
		long value;
		int offset;

		/* Strip off the amazing number of layers of bloat that PKCS #12 
		   lards a certificate with.  There are any number of different
		   interpretations of how to store certificates in a PKCS #12 file, 
		   the following is the one that (eventually) ends up in a 
		   certificate that we can read */
		status = readShortInteger( &stream, &value );
		if( cryptStatusError( status ) || value != 3 )
			{
			sMemDisconnect( &stream );
			return( CRYPT_ERROR_BADDATA );
			}
		readSequence( &stream, NULL );
		readFixedOID( &stream, OID_CMS_DATA, sizeofOID( OID_CMS_DATA ) );
		readConstructed( &stream, NULL, 0 );
		readOctetStringHole( &stream, NULL, 8, DEFAULT_TAG );
		readSequence( &stream, NULL );
		readSequence( &stream, NULL );
		readFixedOID( &stream, OID_CMS_DATA, sizeofOID( OID_CMS_DATA ) );
		readConstructed( &stream, NULL, 0 );
		readOctetStringHole( &stream, NULL, 8, DEFAULT_TAG );
		readSequence( &stream, NULL );
		readSequence( &stream, NULL );
		readFixedOID( &stream, 
					  MKOID( "\x06\x0B\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x0A\x01\x03" ),
					  13 );
		readConstructed( &stream, NULL, 0 );
		readSequence( &stream, NULL );
		readFixedOID( &stream, 
					  MKOID( "\x06\x0A\x2A\x86\x48\x86\xF7\x0D\x01\x09\x16\x01" ),
					  12 );
		readConstructed( &stream, NULL, 0 );
		readOctetStringHole( &stream, &length, 8, DEFAULT_TAG );
		offset = stell( &stream );	/* Certificate start */
		readSequence( &stream, NULL );
		status = readSequence( &stream, NULL );
		sMemDisconnect( &stream );
		if( cryptStatusError( status ) )
			return( status );

		/* We've finally reached the certificate, record its offset and 
		   length */
		*objectOffset = offset;
		*objectLength = length;
		*objectType = CRYPT_CERTTYPE_CERTIFICATE;
		return( isLongData ? CRYPT_ERROR_OVERFLOW : CRYPT_OK );
		}

	/* Read the inner sequence */
	if( isLongData )
		{
		long longLength;

		status = readLongSequence( &stream, &longLength );
		if( cryptStatusOK( status ) )
			{
			/* If it's an (invalid) indefinite-length encoding we can't do 
			   anything with it */
			if( longLength == CRYPT_UNUSED )
				status = CRYPT_ERROR_BADDATA;
			else
				length = ( int ) longLength;
			}
		}
	else
		status = readSequence( &stream, &length );
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( &stream );
		return( status );
		}

	/* Skip optional tagged fields and the INTEGER value */
	if( peekTag( &stream ) == MAKE_CTAG( 0 ) )
		status = readUniversal( &stream );
	if( peekTag( &stream ) == MAKE_CTAG( 1 ) )
		status = readUniversal( &stream );
	if( peekTag( &stream ) == MAKE_CTAG( 2 ) )
		status = readUniversal( &stream );
	if( peekTag( &stream ) == BER_INTEGER )
		status = readUniversal( &stream );
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( &stream );
		return( status );
		}
	if( length <= 0 )
		{
		/* PKI user object with absent (non-specified) DN */
		sMemDisconnect( &stream );
		*objectType = CRYPT_CERTTYPE_PKIUSER;
		return( isLongData ? CRYPT_ERROR_OVERFLOW : CRYPT_OK );
		}

⌨️ 快捷键说明

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