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

📄 certio.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 3 页
字号:
	CERT_INFO *certInfoPtr;
	CRYPT_CERTFORMAT_TYPE format = CRYPT_CERTFORMAT_NONE;
	CRYPT_CERTTYPE_TYPE type;
	STREAM stream;
	int ( *readCertObjectFunction )( STREAM *stream, CERT_INFO *certInfoPtr );
	void *certObjectPtr = ( void * ) certObject, *certBuffer;
	int length, offset, initStatus = CRYPT_OK, status;

	*certificate = CRYPT_ERROR;

	/* If it's not a special-case format, check whether it's an S/MIME or 
	   base64-encoded certificate object */
	if( formatType == CERTFORMAT_NORMAL )
		{
		if( ( length = smimeCheckHeader( certObject, 
										 certObjectLength ) ) != 0 )
			format = CRYPT_ICERTFORMAT_SMIME_CERTIFICATE;
		else
			if( ( length = base64checkHeader( certObject, 
											  certObjectLength ) ) != 0 )
				format = CRYPT_CERTFORMAT_TEXT_CERTIFICATE;
		if( length )
			{
			int decodedLength;

			/* It's base64 / S/MIME-encoded, decode it into a temporary 
			   buffer */
			decodedLength = base64decodeLen( ( const char * ) certObject + length,
											 certObjectLength );
			if( decodedLength <= 128 || decodedLength > 8192 )
				return( CRYPT_ERROR_BADDATA );
			if( ( certObjectPtr = malloc( decodedLength ) ) == NULL )
				return( CRYPT_ERROR_MEMORY );
			if( !base64decode( certObjectPtr, ( const char * ) certObject +
							   length, 0, format ) )
				{
				free( certObjectPtr );
				return( CRYPT_ERROR_BADDATA );
				}
			}
		}

	/* Check the object to determine its type and length, and check the
	   encoding if necessary */
	status = getCertObjectInfo( certObjectPtr, certObjectLength, &offset, 
								&length, &type, formatType );
	if( !cryptStatusError( status ) && formatType != CERTFORMAT_SSLCHAIN )
		status = checkObjectEncoding( ( BYTE * ) certObjectPtr + offset, 
									  length );
	if( cryptStatusError( status ) )
		{
		if( certObjectPtr != certObject )
			free( certObjectPtr );
		return( status );
		}
	status = CRYPT_OK;	/* checkEncoding() returns a length */

	/* If it's a cert chain, this is handled specially since we need to
	   import a plurality of certs at once */
	if( type == CRYPT_CERTTYPE_CERTCHAIN || \
		type == CRYPT_CERTTYPE_CMS_CERTSET || \
		type == CRYPT_CERTTYPE_SSL_CERTCHAIN )
		{
		/* Read the cert chain into a collection of internal cert resources.
		   This returns a handle to the leaf cert in the chain, with the
		   remaining certs being accessible within it via the cert 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, cryptOwner, type, 
								keyIDtype, keyID, keyIDlength, 
								( formatType == CERTFORMAT_DATAONLY ) ? \
									TRUE : FALSE );
		sMemDisconnect( &stream );
		if( certObjectPtr != certObject )
			free( certObjectPtr );
		if( cryptStatusError( status ) )
			return( status );
		return( length );
		}

	/* Select the function to use to read the certificate object */
	switch( type )
		{
		case CRYPT_CERTTYPE_CERTIFICATE:
			readCertObjectFunction = readCertInfo;
			break;

		case CRYPT_CERTTYPE_ATTRIBUTE_CERT:
			readCertObjectFunction = readAttributeCertInfo;
			break;

		case CRYPT_CERTTYPE_CERTREQUEST:
			readCertObjectFunction = readCertRequestInfo;
			break;

		case CRYPT_CERTTYPE_REQUEST_CERT:
			readCertObjectFunction = readCRMFRequestInfo;
			break;

		case CRYPT_CERTTYPE_REQUEST_REVOCATION:
			readCertObjectFunction = readRevRequestInfo;
			break;

		case CRYPT_CERTTYPE_CRL:
			readCertObjectFunction = readCRLInfo;
			break;

		case CRYPT_CERTTYPE_CMS_ATTRIBUTES:
			readCertObjectFunction = readCMSAttributes;
			break;

		case CRYPT_CERTTYPE_OCSP_RESPONSE:
			readCertObjectFunction = readOCSPResponseInfo;
			break;

		case CRYPT_CERTTYPE_OCSP_REQUEST:
			readCertObjectFunction = readOCSPRequestInfo;
			break;

		case CRYPT_CERTTYPE_PKIUSER:
			readCertObjectFunction = readPKIUserInfo;
			break;

		default:
			assert( NOTREACHED );
		}

	/* 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,
	   which 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.  The readXXX() function record pointers to the
	   required encoded fields so 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 cert objects
	   need to be kept around anyway for sig checks and possible re-export */
	if( ( certBuffer = malloc( length ) ) == NULL )
		status = CRYPT_ERROR_MEMORY;
	if( cryptStatusOK( status ) )
		/* Create the certificate object */
		status = createCertificateInfo( &certInfoPtr, cryptOwner, type );
	if( cryptStatusError( status ) )
		{
		if( certObjectPtr != certObject )
			free( certObjectPtr );
		free( 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( formatType == CERTFORMAT_DATAONLY )
		certInfoPtr->flags |= CERT_FLAG_DATAONLY;

	/* 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 )
		readSequence( &stream, NULL );	/* Skip the outer wrapper */
	status = readCertObjectFunction( &stream, certInfoPtr );
	sMemDisconnect( &stream );
	if( certObjectPtr != certObject )
		free( certObjectPtr );
	if( cryptStatusError( status ) )
		{
		/* The import failed, make sure the object gets destroyed when we 
		   notify the kernel that the setup process is complete */
		krnlSendNotifier( *certificate, RESOURCE_IMESSAGE_DESTROY );
		initStatus = status;
		}

	/* We've finished setting up the object-type-specific info, tell the 
	   kernel the object is ready for use */
	unlockResource( certInfoPtr );
	status = krnlSendMessage( *certificate, RESOURCE_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 which has a public key associated with it, 
	   notify the kernel that the given context is attached to the cert.  
	   Note that we can only do this at this point because the cert 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 cert we 
	   tell the kernel not to increment its reference count when it attaches
	   it.  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->iCryptContext != CRYPT_ERROR )
		krnlSendMessage( *certificate, RESOURCE_IMESSAGE_SETDEPENDENT,
						 &certInfoPtr->iCryptContext, 
						 SETDEP_OPTION_NOINCREF );
	krnlSendMessage( *certificate, RESOURCE_IMESSAGE_SETATTRIBUTE,
					 MESSAGE_VALUE_UNUSED, CRYPT_IATTRIBUTE_INITIALISED );
	return( length );
	}

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

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

int exportCert( void *certObject, int *certObjectLength,
				const CRYPT_CERTFORMAT_TYPE certFormatType,
				const CERT_INFO *certInfoPtr, const int maxLength )
	{
	/* If it's a binary format, the base format is the actual format type.
	   If it's a text (base64) format, the base format is given by subtracting
			the difference between the text and binary formats */
	const CRYPT_CERTFORMAT_TYPE baseFormatType = \
		( certFormatType < CRYPT_CERTFORMAT_TEXT_CERTIFICATE ) ? \
			certFormatType : 
			certFormatType - ( CRYPT_CERTFORMAT_TEXT_CERTIFICATE - 1 );
	STREAM stream;
	void *buffer;
	int length, encodedLength, status;

	/* Determine how big the output object will be */
	if( baseFormatType == CRYPT_CERTFORMAT_CERTCHAIN )
		{
		STREAM nullStream;
		int status;

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

		sMemOpen( &nullStream, NULL, 0 );
		status = writeCertChain( &nullStream, certInfoPtr );
		length = ( int ) stell( &nullStream );
		sMemClose( &nullStream );
		if( cryptStatusError( status ) )
			return( status );
		}
	else
		length = certInfoPtr->certificateSize;
	encodedLength = ( certFormatType >= CRYPT_CERTFORMAT_TEXT_CERTIFICATE ) ? \
		base64encodeLen( length, certInfoPtr->type ) : length;

	/* Set up the length information */
	*certObjectLength = encodedLength;
	if( certObject == NULL )
		return( CRYPT_OK );
	if( encodedLength > maxLength )
		return( CRYPT_ERROR_OVERFLOW );
	if( checkBadPtrWrite( 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 )
		{
		memcpy( certObject, certInfoPtr->certificate, length );
		return( CRYPT_OK );
		}
	if( certFormatType == CRYPT_CERTFORMAT_TEXT_CERTIFICATE )
		{
		base64encode( certObject, certInfoPtr->certificate,
					  certInfoPtr->certificateSize, certInfoPtr->type );
		return( CRYPT_OK );
		}

	/* It's a straight cert chain, write it directly to the output */
	if( certFormatType == CRYPT_CERTFORMAT_CERTCHAIN )
		{
		sMemOpen( &stream, certObject, length );
		status = writeCertChain( &stream, certInfoPtr );
		sMemDisconnect( &stream );
		return( status );
		}

	/* It's a base64 / S/MIME-encoded cert chain, write it to a temporary
	   buffer and then encode it to the output */
	assert( certFormatType == CRYPT_CERTFORMAT_TEXT_CERTCHAIN );
	if( ( buffer = malloc( length ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	sMemOpen( &stream, buffer, length );
	status = writeCertChain( &stream, certInfoPtr );
	if( cryptStatusOK( status ) )
		base64encode( certObject, buffer, length, CRYPT_CERTTYPE_CERTCHAIN );
	sMemClose( &stream );
	free( buffer );

	return( status );
	}

⌨️ 快捷键说明

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