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

📄 certio.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 3 页
字号:
	if( !memcmp( oid, OID_CMS_SIGNEDDATA, oidLength ) )
		isCertChain = TRUE;
	else
		if( !memcmp( oid, OID_X509_USERCERTIFICATE, oidLength ) )
			{
			/* Oddball wrapper type, set the payload offset to point to 
			   the certificate and indicate no wrapper present */
			*offset = ( int ) 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 );
	readConstructed( stream, NULL, 0 );
	status = readSequence( 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;

		/* 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 cert 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 )
			sSkip( stream, value );

		/* Read the ContentInfo header, contentType OID and the inner
		   content encapsulation */
		readSequence( stream, NULL );
		status = readOID( stream, OID_CMS_DATA );
		if( cryptStatusError( status ) )
			return( status );
		checkEOC( 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;
	CRYPT_CERTTYPE_TYPE wrapperType = CRYPT_CERTTYPE_NONE;
	CRYPT_CERTTYPE_TYPE type = CRYPT_CERTTYPE_NONE;
	int tag, length, status;

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

	sMemConnect( &stream, object, objectTotalLength );

	/* If it's an SSL cert chain there's no recognisable tagging, however the
	   caller will have told us what it is */
	if( formatType == CERTFORMAT_SSLCHAIN )
		{
		BYTE *objectPtr = ( void * ) object;

		*objectLength = objectTotalLength;
		*objectType = CRYPT_CERTTYPE_SSL_CERTCHAIN;
		return( CRYPT_OK );
		}

	/* First we check for the easy ones, CMS attributes or a CMS cert chain, 
	   both of which begin with a [0] IMPLICIT SET */
	if( peekTag( &stream ) == MAKE_CTAG( 0 ) || \
		formatType == CERTFORMAT_CERTSET )
		{
		*objectLength = objectTotalLength;
		*objectType = ( formatType == CERTFORMAT_CERTSET ) ? \
				CRYPT_CERTTYPE_CMS_CERTSET : CRYPT_CERTTYPE_CMS_ATTRIBUTES;
		return( CRYPT_OK );
		}

	/* Check that the start of the object is in order and gets its length */
	status = readSequence( &stream, &length );
	if( cryptStatusOK( status ) && !length )
		status = getObjectLength( object, objectTotalLength );
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( &stream );
		return( status );
		}
	*objectLength = length ? ( int ) sizeofObject( length ) : status;

	/* 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( 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 which PKCS #12 
		   lards a certificate with */
		status = readShortInteger( &stream, &value );
		if( cryptStatusError( status ) || value != 3 )
			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 = ( int ) 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( CRYPT_OK );
		}

	/* Read the inner sequence and skip optional tagged fields and the
	   INTEGER value */
	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 );
	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( 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( 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( 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 */
	readSequence( &stream, &length );
	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( CRYPT_OK );
			}
		if( tag == BER_TIME_UTC || tag == BER_TIME_GENERALIZED )
			{
			*objectType = CRYPT_CERTTYPE_CRL;
			return( CRYPT_OK );
			}
		return( CRYPT_ERROR_BADDATA );
		}
	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 */
	readSequence( &stream, &length );
	tag = peekTag( &stream );
	if( tag == BER_SEQUENCE || \
		( tag >= MAKE_CTAG( 0 ) && tag <= MAKE_CTAG( 3 ) ) )
		{
		sMemDisconnect( &stream );
		*objectType = CRYPT_CERTTYPE_OCSP_REQUEST;
		return( CRYPT_OK );
		}

	/* It's nothing identifiable */
	sMemDisconnect( &stream );
	return( CRYPT_ERROR_BADDATA );
	}

/****************************************************************************
*																			*
*								Import/Export Functions						*
*																			*
****************************************************************************/

/* Import a certificate object.  If the import type is set to create a data-
   only cert, its publicKeyInfo pointer is set to the start of the encoded 
   public key to allow it to be decoded later.  Returns the length of the 
   certificate */

int importCert( const void *certObject, const int certObjectLength,
				CRYPT_CERTIFICATE *certificate,
				const CRYPT_USER cryptOwner,
				const CRYPT_KEYID_TYPE keyIDtype,
				const void *keyID, const int keyIDlength,
				const CERTFORMAT_TYPE formatType )
	{

⌨️ 快捷键说明

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