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

📄 imp_exp.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:
							  &complianceLevel, 
							  CRYPT_OPTION_CERT_COMPLIANCELEVEL );
	if( cryptStatusError( status ) )
		return( status );

	/* If it's not a pre-specified or special-case format check whether it's 
	   some form of encoded certificate object */
	if( formatHint == CRYPT_CERTTYPE_NONE )
		{
		status = checkTextEncoding( certObject, certObjectLength,
									&certObjectPtr, &objectLength );
		if( cryptStatusError( status ) )
			{
			if( status != OK_SPECIAL )
				return( status );

			/* The certificate object has been decoded into a temporary 
			   buffer, remember that we have to free it before we exit */
			isDecodedObject = TRUE;
			}		
		}

	/* Determine the object's type and length and check the encoding unless
	   we're running in oblivious mode */
	status = getCertObjectInfo( certObjectPtr, objectLength, &offset, 
								&length, &type, formatHint );
	if( cryptStatusOK( status ) && \
		complianceLevel > CRYPT_COMPLIANCELEVEL_OBLIVIOUS && \
		formatHint != CRYPT_ICERTTYPE_SSL_CERTCHAIN )
		{
		if( cryptStatusError( \
				checkObjectEncoding( ( BYTE * ) certObjectPtr + offset, 
									 length ) ) )
			status = CRYPT_ERROR_BADDATA;
		}
	if( cryptStatusError( status ) )
		{
		if( isDecodedObject )
			clFree( "importCert", certObjectPtr );
		return( status );
		}

	/* If it's a certificate chain this is handled specially since we need 
	   to import a plurality of certificates at once */
	if( type == CRYPT_CERTTYPE_CERTCHAIN || \
		type == CRYPT_ICERTTYPE_CMS_CERTSET || \
		type == CRYPT_ICERTTYPE_SSL_CERTCHAIN )
		{
		/* Read the certificate chain into a collection of internal 
		   certificate objects.  This returns a handle to the leaf 
		   certificate in the chain with the remaining certificates being 
		   accessible within it via the certificate cursor functions.  
		   Because the different chain types are only used to distinguish 
		   the chain wrapper type on import, the final object type which is 
		   created is always a CRYPT_CERTTYPE_CERTCHAIN no matter what the 
		   import format was */
		sMemConnect( &stream, ( BYTE * ) certObjectPtr + offset, length );
		if( type == CRYPT_CERTTYPE_CERTCHAIN )
			readSequence( &stream, NULL );	/* Skip the outer wrapper */
		status = readCertChain( &stream, certificate, iCryptOwner, type, 
								keyIDtype, keyID, keyIDlength, 
								( formatHint == CRYPT_ICERTTYPE_DATAONLY ||
								  formatHint == CRYPT_ICERTTYPE_CTL ) ? \
									TRUE : FALSE );
		sMemDisconnect( &stream );
		if( isDecodedObject )
			clFree( "importCert", certObjectPtr );
		return( status );
		}

	ENSURES( keyIDtype == CRYPT_KEYID_NONE && keyID == NULL && \
			 keyIDlength == 0 );

	/* Select the function to use to read the certificate object */
	readCertFunction = getCertReadFunction( type );
	if( readCertFunction == NULL )
		{
		if( isDecodedObject )
			clFree( "importCert", certObjectPtr );
		retIntError();
		}
	
	/* Allocate a buffer to store a copy of the object so we can preserve the
	   original for when it's needed again later, and try and create the
	   certificate object.  All the objects (including the CMS attributes,
	   that in theory aren't needed for anything further) need to be kept
	   around in their encoded form, which is often incorrect and therefore
	   can't be reconstructed from the decoded info.  The readXXX() functions 
	   record pointers to the required encoded fields so that they can be 
	   recovered later in their (possibly incorrect) form and these pointers 
	   need to be to a persistent copy of the encoded object.  In addition the 
	   certificate objects need to be kept around anyway for signature checks 
	   and possible re-export */
	if( ( certBuffer = clAlloc( "importCert", length ) ) == NULL )
		{
		if( isDecodedObject )
			clFree( "importCert", certObjectPtr );
		return( CRYPT_ERROR_MEMORY );
		}

	/* Create the certificate object */
	status = createCertificateInfo( &certInfoPtr, iCryptOwner, type );
	if( cryptStatusError( status ) )
		{
		if( isDecodedObject )
			clFree( "importCert", certObjectPtr );
		clFree( "importCert", certBuffer );
		return( status );
		}
	*certificate = status;

	/* If we're doing a deferred read of the public key components (they'll
	   be decoded later when we know whether we need them) set the data-only
	   flag to ensure we don't try to decode them */
	if( formatHint == CRYPT_ICERTTYPE_DATAONLY || \
		formatHint == CRYPT_ICERTTYPE_CTL )
		certInfoPtr->flags |= CERT_FLAG_DATAONLY;

	/* If we're reading a single entry from a CRL, indicate that the 
	   resulting object is a standalone single CRL entry rather than a proper
	   CRL */
	if( formatHint == CRYPT_ICERTTYPE_REVINFO )
		certInfoPtr->flags |= CERT_FLAG_CRLENTRY;

	/* Copy in the certificate object for later use */
	memcpy( certBuffer, ( BYTE * ) certObjectPtr + offset, length );
	certInfoPtr->certificate = certBuffer;
	certInfoPtr->certificateSize = length;

	/* Parse the object into the certificate.  Note that we have to use the
	   copy in the certBuffer rather than the original since the readXXX()
	   functions record pointers to various encoded fields */
	sMemConnect( &stream, certBuffer, length );
	if( type != CRYPT_CERTTYPE_CMS_ATTRIBUTES && \
		type != CRYPT_CERTTYPE_RTCS_REQUEST && \
		type != CRYPT_CERTTYPE_RTCS_RESPONSE )
		{
		/* Skip the outer wrapper */
		readLongSequence( &stream, NULL );
		}
	status = readCertFunction( &stream, certInfoPtr );
	sMemDisconnect( &stream );
	if( isDecodedObject )
		clFree( "importCert", certObjectPtr );
	if( cryptStatusError( status ) )
		{
		/* The import failed, make sure that the object gets destroyed when 
		   we notify the kernel that the setup process is complete.  We also
		   have to explicitly destroy the attached context since at this
		   point it hasn't been associated with the certificate yet so it
		   won't be automatically destroyed by the kernel when the 
		   certificate is destroyed */
		krnlSendNotifier( *certificate, IMESSAGE_DESTROY );
		if( certInfoPtr->iPubkeyContext != CRYPT_ERROR )
			{
			krnlSendNotifier( certInfoPtr->iPubkeyContext, 
							  IMESSAGE_DECREFCOUNT );
			certInfoPtr->iPubkeyContext = CRYPT_ERROR;
			}
		initStatus = status;
		}

	/* We've finished setting up the object-type-specific info, tell the 
	   kernel that the object is ready for use */
	status = krnlSendMessage( *certificate, IMESSAGE_SETATTRIBUTE, 
							  MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );
	if( cryptStatusError( initStatus ) || cryptStatusError( status ) )
		{
		*certificate = CRYPT_ERROR;
		return( cryptStatusError( initStatus ) ? initStatus : status );
		}

	/* If this is a type of object that has a public key associated with it, 
	   notify the kernel that the given context is attached to the 
	   certificate.  Note that we can only do this at this point because the 
	   certificate object can't receive general messages until its status is 
	   set to OK.  In addition since this is an internal object used only by 
	   the certificate we tell the kernel not to increment its reference 
	   count when it attaches it to the certificate object.  Finally, we're 
	   ready to go so we mark the object as initialised (we can't do this 
	   before the initialisation is complete because the kernel won't 
	   forward the message to a not-ready-for-use object)*/
	if( certInfoPtr->iPubkeyContext != CRYPT_ERROR )
		krnlSendMessage( *certificate, IMESSAGE_SETDEPENDENT,
						 &certInfoPtr->iPubkeyContext, 
						 SETDEP_OPTION_NOINCREF );
	return( krnlSendMessage( *certificate, IMESSAGE_SETATTRIBUTE,
							 MESSAGE_VALUE_UNUSED, 
							 CRYPT_IATTRIBUTE_INITIALISED ) );
	}

/* Export a certificate/certification request.  This just writes the
   internal encoded object to an external buffer.  For certificate/
   certificate chain export the possibilities are as follows:

						Export
	Type  |		Cert				Chain
	------+--------------------+---------------
	Cert  | Cert			   | Cert as chain
		  |					   |
	Chain | Currently selected | Chain
		  | cert in chain	   |					*/

CHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5 ) ) \
int exportCert( OUT_BUFFER_OPT( certObjectMaxLength, *certObjectLength ) \
					void *certObject, 
				IN_LENGTH const int certObjectMaxLength, 
				OUT_LENGTH_Z int *certObjectLength,
				IN_ENUM( CRYPT_CERTFORMAT ) \
					const CRYPT_CERTFORMAT_TYPE certFormatType,
				const CERT_INFO *certInfoPtr )
	{
	const CRYPT_CERTFORMAT_TYPE baseFormatType = \
		( certFormatType == CRYPT_CERTFORMAT_TEXT_CERTIFICATE || \
		  certFormatType == CRYPT_CERTFORMAT_XML_CERTIFICATE ) ? \
			CRYPT_CERTFORMAT_CERTIFICATE : \
		( certFormatType == CRYPT_CERTFORMAT_TEXT_CERTCHAIN || \
		  certFormatType == CRYPT_CERTFORMAT_XML_CERTCHAIN ) ? \
			CRYPT_CERTFORMAT_CERTCHAIN : \
			certFormatType;
	STREAM stream;
	void *buffer;
	int length, encodedLength, status;

	assert( ( certObject == NULL && certObjectMaxLength == 0 ) || \
			isWritePtr( certObject, certObjectMaxLength ) );
	assert( isWritePtr( certObjectLength, sizeof( int ) ) );
	assert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );

	REQUIRES( ( certObject == NULL && certObjectMaxLength == 0 ) || \
			  ( certObject != NULL && \
				certObjectMaxLength > 0 && \
				certObjectMaxLength < MAX_INTLENGTH ) );
	REQUIRES( certFormatType > CRYPT_CERTFORMAT_NONE && \
			  certFormatType < CRYPT_CERTFORMAT_LAST );

	/* If it's an internal format, write it and exit */
	if( certFormatType == CRYPT_ICERTFORMAT_CERTSET || \
		certFormatType == CRYPT_ICERTFORMAT_CERTSEQUENCE || \
		certFormatType == CRYPT_ICERTFORMAT_SSL_CERTCHAIN )
		{
		*certObjectLength = ( int ) \
				sizeofCertCollection( certInfoPtr, certFormatType );
		if( certObject == NULL )
			return( CRYPT_OK );
		if( *certObjectLength > certObjectMaxLength )
			return( CRYPT_ERROR_OVERFLOW );
		sMemOpen( &stream, certObject, *certObjectLength );
		status = writeCertCollection( &stream, certInfoPtr,
									  certFormatType );
		sMemDisconnect( &stream );
		return( status );
		}

	/* Determine how big the output object will be */
	length = encodedLength = certInfoPtr->certificateSize;
	if( baseFormatType == CRYPT_CERTFORMAT_CERTCHAIN )
		{
		STREAM nullStream;

		ENSURES( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
				 certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );

		sMemNullOpen( &nullStream );
		status = writeCertChain( &nullStream, certInfoPtr );
		if( cryptStatusOK( status ) )
			length = encodedLength = stell( &nullStream );
		sMemClose( &nullStream );
		if( cryptStatusError( status ) )
			return( status );
		}
	if( baseFormatType != certFormatType )
		{
		status = base64encodeLen( length, &encodedLength, 
								  certInfoPtr->type );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Set up the length information */
	*certObjectLength = encodedLength;
	if( certObject == NULL )
		return( CRYPT_OK );
	if( encodedLength > certObjectMaxLength )
		return( CRYPT_ERROR_OVERFLOW );
	if( !isWritePtr( certObject, encodedLength ) )
		return( CRYPT_ARGERROR_STR1 );

	/* If it's a simple object, write either the DER-encoded object or its
	   base64 / S/MIME-encoded form directly to the output */
	if( certFormatType == CRYPT_CERTFORMAT_CERTIFICATE || \
		certFormatType == CRYPT_ICERTFORMAT_DATA )
		{
		memcpy( certObject, certInfoPtr->certificate, length );
		ENSURES( !cryptStatusError( checkObjectEncoding( certObject, \
														 length ) ) );

		return( CRYPT_OK );
		}
	if( certFormatType == CRYPT_CERTFORMAT_TEXT_CERTIFICATE || \
		certFormatType == CRYPT_CERTFORMAT_XML_CERTIFICATE )
		{
		return( base64encode( certObject, certObjectMaxLength, 
							  certObjectLength, certInfoPtr->certificate,
							  certInfoPtr->certificateSize, 
							  certInfoPtr->type ) );
		}

	/* It's a straight certificate chain, write it directly to the output */
	if( certFormatType == CRYPT_CERTFORMAT_CERTCHAIN )
		{
		sMemOpen( &stream, certObject, length );
		status = writeCertChain( &stream, certInfoPtr );
		sMemDisconnect( &stream );
		ENSURES( cryptStatusError( status ) || \
				 !cryptStatusError( checkObjectEncoding( certObject, \
														 length ) ) );

		return( status );
		}

	/* It's a base64 / S/MIME-encoded certificate chain, write it to a 
	   temporary buffer and then encode it to the output */
	ENSURES( certFormatType == CRYPT_CERTFORMAT_TEXT_CERTCHAIN || \
			 certFormatType == CRYPT_CERTFORMAT_XML_CERTCHAIN );
	if( ( buffer = clAlloc( "exportCert", length ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	sMemOpen( &stream, buffer, length );
	status = writeCertChain( &stream, certInfoPtr );
	if( cryptStatusOK( status ) )
		{
		status = base64encode( certObject, certObjectMaxLength, 
							   certObjectLength, buffer, length, 
							   CRYPT_CERTTYPE_CERTCHAIN );
		}
	sMemClose( &stream );
	clFree( "exportCert", buffer );

	return( status );
	}

⌨️ 快捷键说明

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