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

📄 certio.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 3 页
字号:
		if( cryptStatusOK( status ) )
			status = readSet( stream, &value );
		if( cryptStatusError( status ) )
			return( status );
		if( value > 0 )
			sSkip( stream, value );

		/* Read the ContentInfo header, contentType OID and the inner content 
		   encapsulation.  Sometimes we may (incorrectly) get passed actual 
		   signed data (rather than degenerate zero-length data signifying a 
		   pure cert chain), if there's data present we skip it */
		readSequenceI( stream, &innerLength );
		status = readRawObject( stream, NULL, &oidLength, MAX_OID_SIZE, 
								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 cert 
			   chain */
			if( innerLength > sizeofObject( oidLength ) )
				readUniversal( stream );
		readConstructed( stream, NULL, 0 );
		}

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

static int getCertObjectInfo( const void *object, const int objectTotalLength,
							  int *objectOffset, int *objectLength, 
							  CRYPT_CERTTYPE_TYPE *objectType,
							  const CERTFORMAT_TYPE formatType )
	{
	STREAM stream;
	BOOLEAN isContextTagged = FALSE, isLongData = FALSE;
	int tag, length, status;

	/* Set initial default values */
	*objectOffset = 0;
	*objectLength = CRYPT_ERROR;
	*objectType = CRYPT_CERTTYPE_NONE;

	/* If it's an SSL cert chain there's no recognisable tagging, however the
	   caller will have told us what it is */
	if( formatType == 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 ) || \
		formatType == CRYPT_ICERTTYPE_CMS_CERTSET )
		isContextTagged = TRUE;
	status = readConstructedI( &stream, &length, \
							   isContextTagged ? 0 : DEFAULT_TAG );
#if INT_MAX > 32767
	if( status == CRYPT_ERROR_OVERFLOW )
		{
		long longLength;

		/* CRLs can grow without bounds as more and more certs 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;
			}
		}
	else
#endif /* Non-16-bit systems */
		if( cryptStatusOK( status ) && length == CRYPT_UNUSED )
			{
			/* It's a indefinite-length object, burrow into it to find it's
			   actual length */
			status = getObjectLength( object, objectTotalLength );
#if INT_MAX > 32767
			if( status == CRYPT_ERROR_OVERFLOW )
				status = getLongObjectLength( object, objectTotalLength );
#endif /* Non-16-bit systems */
			}
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( &stream );
		return( status );
		}
	*objectLength = ( length != CRYPT_UNUSED ) ? \
					( int ) sizeofObject( length ) : status;

	/* 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( formatType != CRYPT_CERTTYPE_NONE )
		{
		sMemDisconnect( &stream );

		if( formatType > CRYPT_CERTTYPE_NONE && \
			formatType < CRYPT_CERTTYPE_LAST )
			*objectType = formatType;
		else
			switch( formatType )
				{
				case CERTFORMAT_DATAONLY:
					/* Standard certificate but created without creating a 
					   context for the accompanying public key */
					*objectType = CRYPT_CERTTYPE_CERTIFICATE;
					break;

				case CERTFORMAT_CTL:
					/* Cert chain used as a container for trusted certs, 
					   effectively a chain of CERTFORMAT_DATAONLY certs */
					*objectType = CRYPT_CERTTYPE_CERTCHAIN;
					break;

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

				default:
					assert( NOTREACHED );
					return( CRYPT_ERROR_BADDATA );
				}
										
		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 cert.sequence,
	   there'll be an object identifier present.  Some sources also wrap
	   certs 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 certs in a PKCS #12 file, the
		   following is the one that (eventually) ends up in a cert that
		   we can read */
		status = readShortInteger( &stream, &value );
		if( cryptStatusError( status ) || value != 3 )
			{
			sMemDisconnect( &stream );
			return( CRYPT_ERROR_BADDATA );
			}
		readSequence( &stream, NULL );
		readOID( &stream, OID_CMS_DATA );
		readConstructed( &stream, NULL, 0 );
		readOctetStringHole( &stream, NULL, DEFAULT_TAG );
		readSequence( &stream, NULL );
		readSequence( &stream, NULL );
		readOID( &stream, OID_CMS_DATA );
		readConstructed( &stream, NULL, 0 );
		readOctetStringHole( &stream, NULL, DEFAULT_TAG );
		readSequence( &stream, NULL );
		readSequence( &stream, NULL );
		readOID( &stream, 
				 MKOID( "\x06\x0B\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x0A\x01\x03" ) );
		readConstructed( &stream, NULL, 0 );
		readSequence( &stream, NULL );
		readOID( &stream, 
				 MKOID( "\x06\x0A\x2A\x86\x48\x86\xF7\x0D\x01\x09\x16\x01" ) );
		readConstructed( &stream, NULL, 0 );
		readOctetStringHole( &stream, &length, 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 cert, record its offset and length */
		*objectOffset = offset;
		*objectLength = length;
		*objectType = CRYPT_CERTTYPE_CERTIFICATE;
		return( isLongData ? CRYPT_ERROR_OVERFLOW : CRYPT_OK );
		}

	/* Read the inner sequence and skip optional tagged fields and the
	   INTEGER value */
	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( peekTag( &stream ) == MAKE_CTAG( 0 ) )
		readUniversal( &stream );
	if( peekTag( &stream ) == MAKE_CTAG( 1 ) )
		readUniversal( &stream );
	if( peekTag( &stream ) == MAKE_CTAG( 2 ) )
		readUniversal( &stream );
	if( peekTag( &stream ) == BER_INTEGER )
		readUniversal( &stream );
	if( cryptStatusOK( status ) )
		status = sGetStatus( &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 );
		}

	/* If we've hit a [1] it's an attribute cert, if we've hit a
	   GeneralizedTime it's an OCSP response, if we've hit a SET it's PKI
	   user info, and if we've hit a [0] or [1] primitive tag (implicitly 
	   tagged INTEGER) or [3]...[9] it's a CRMF revocation request */
	tag = peekTag( &stream );
	if( tag == MAKE_CTAG( 1 ) || tag == BER_TIME_GENERALIZED || \
		tag == BER_SET )
		{
		sMemDisconnect( &stream );
		*objectType = \
			( tag == MAKE_CTAG( 1 ) ) ? CRYPT_CERTTYPE_ATTRIBUTE_CERT : \
			( tag == BER_TIME_GENERALIZED ) ? \
				CRYPT_CERTTYPE_OCSP_RESPONSE : CRYPT_CERTTYPE_PKIUSER;
		return( isLongData ? CRYPT_ERROR_OVERFLOW : CRYPT_OK );
		}
	if( tag == MAKE_CTAG_PRIMITIVE( 0 ) || \
		tag == MAKE_CTAG_PRIMITIVE( 1 ) || \
		( tag >= MAKE_CTAG( 3 ) && tag <= MAKE_CTAG( 9 ) ) )
		{
		sMemDisconnect( &stream );
		*objectType = CRYPT_CERTTYPE_REQUEST_REVOCATION;
		return( isLongData ? CRYPT_ERROR_OVERFLOW : CRYPT_OK );
		}

	/* Read the next SEQUENCE.  If it's followed by an OID, it's the 
	   AlgorithmIdentifier in a cert or CRL.  If it's followed by a SET, it's
	   the Name in a cert request or attribute cert.  If it's followed by a 
	   tag in the range [0]...[9] it's a horror from CRMF */
	status = readSequence( &stream, &length );
	if( cryptStatusOK( status ) && length <= 0 )
		status = CRYPT_ERROR_BADDATA;
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( &stream );
		return( status );
		}
	tag = peekTag( &stream );
	if( tag == BER_OBJECT_IDENTIFIER )
		{
		/* Skip the AlgorithmIdentifier data and the following Name.  For a
		   cert we now have a SEQUENCE (from the Validity), for a CRL a
		   UTCTime or GeneralizedTime */
		sSkip( &stream, length );
		readUniversal( &stream );
		tag = readTag( &stream );
		sMemDisconnect( &stream );
		if( tag == BER_SEQUENCE )
			{
			*objectType = CRYPT_CERTTYPE_CERTIFICATE;
			return( isLongData ? CRYPT_ERROR_OVERFLOW : CRYPT_OK );
			}
		if( tag == BER_TIME_UTC || tag == BER_TIME_GENERALIZED )
			{
			*objectType = CRYPT_CERTTYPE_CRL;
			return( CRYPT_OK );
			}
		return( CRYPT_ERROR_BADDATA );
		}
	if( isLongData )
		/* Beyond this point we shouldn't be seeing long-length objects */
		return( CRYPT_ERROR_OVERFLOW );
	if( tag >= MAKE_CTAG( 0 ) && tag <= MAKE_CTAG( 9 ) )
		{
		/* Cert requests and revocation requests have the same format, 
		   however revocation requests should have the cert serial number 
		   present while cert requests shouldn't (at least in any normal
		   implementation), so we use this to distinguish the two.  If
		   this ever fails in the future, we can also look for things like
		   [6] (the public key) as a clue that it's a cert request */
		sMemDisconnect( &stream );
		*objectType = ( tag == MAKE_CTAG( 1 ) ) ? \
				CRYPT_CERTTYPE_REQUEST_REVOCATION : CRYPT_CERTTYPE_REQUEST_CERT;
		return( CRYPT_OK );
		}
	if( tag == BER_SET )
		{
		sSkip( &stream, length );
		readSequence( &stream, NULL );
		tag = readTag( &stream );
		sMemDisconnect( &stream );
		if( tag == BER_OBJECT_IDENTIFIER )
			{
			*objectType = CRYPT_CERTTYPE_ATTRIBUTE_CERT;
			return( CRYPT_OK );
			}
		if( tag == BER_SEQUENCE )
			{
			*objectType = CRYPT_CERTTYPE_CERTREQUEST;
			return( CRYPT_OK );
			}
		return( CRYPT_ERROR_BADDATA );
		}

	/* Read the next SEQUENCE.  If it's followed by a yet another SEQUENCE 
	   or a tag from [0] ... [3] it's an OCSP request, if it's followed by
	   an OCTET STRING it's a cryptlib OCSP response */
	readSequence( &stream, NULL );
	tag = readTag( &stream );

⌨️ 快捷键说明

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