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

📄 cryptcrt.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:
				getCertWriteFunction( CRYPT_CERTTYPE_CMS_ATTRIBUTES );
		ENSURES( writeCertFunction != NULL );
		sMemOpenOpt( &stream, certData, certDataMaxLength );
		status = writeCertFunction( &stream, certInfoPtr, NULL, 
									CRYPT_UNUSED );
		if( cryptStatusOK( status ) )
			*certDataLength = stell( &stream );
		sMemDisconnect( &stream );

		return( status );
		}

	/* Some objects aren't signed or are pseudo-signed or optionally signed 
	   and have to be handled specially.  RTCS requests and responses are 
	   never signed (they're pure data containers like CMS attributes, with 
	   protection being provided by CMS).  OCSP requests can be optionally 
	   signed but usually aren't, so if we're fed an OCSP request without 
	   any associated encoded data we pseudo-sign it to produce encoded data.  
	   PKI user data is never signed but needs to go through a one-off setup 
	   process to initialise the user data fields, so it has the same 
	   semantics as a pseudo-signed object.  CRMF revocation requests are 
	   never signed (thus ruling out suicide-note revocations) */
	if( ( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST || \
		  certInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE || \
		  certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST || \
		  certInfoPtr->type == CRYPT_CERTTYPE_PKIUSER || \
		  certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION ) && \
		certInfoPtr->certificate == NULL )
		{
		status = signCert( certInfoPtr, CRYPT_UNUSED );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* If we're exporting a single certificate from a chain, lock the 
	   currently selected certificate in the chain and export that */
	if( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN && \
		certInfoPtr->cCertCert->chainPos >= 0 && \
		( certFormat == CRYPT_CERTFORMAT_CERTIFICATE || \
		  certFormat == CRYPT_CERTFORMAT_TEXT_CERTIFICATE || \
		  certFormat == CRYPT_CERTFORMAT_XML_CERTIFICATE ) )
		{
		CERT_INFO *certChainInfoPtr;

		ENSURES( certInfoPtr->cCertCert->chainPos >= 0 && \
				 certInfoPtr->cCertCert->chainPos < MAX_CHAINLENGTH );
		status = krnlAcquireObject( certInfoPtr->cCertCert->chain[ certInfoPtr->cCertCert->chainPos ], 
									OBJECT_TYPE_CERTIFICATE, 
									( void ** ) &certChainInfoPtr,
									CRYPT_ARGERROR_OBJECT );
		if( cryptStatusError( status ) )
			return( status );
		status = exportCert( certData, certDataMaxLength, certDataLength, 
							 certFormat, certChainInfoPtr );
		krnlReleaseObject( certChainInfoPtr->objectHandle );
		return( status );
		}

	ENSURES( ( ( certInfoPtr->flags & CERT_FLAG_CERTCOLLECTION ) && \
			   certInfoPtr->certificate == NULL ) || \
			 certInfoPtr->certificate != NULL );
	return( exportCert( certData, certDataMaxLength, certDataLength, 
						certFormat, certInfoPtr ) );
	}

/****************************************************************************
*																			*
*					Internal Certificate/Key Management Functions			*
*																			*
****************************************************************************/

/* Import a certificate blob or certificate chain by sending get_next_cert 
   messages to the source object to obtain all the certificates in a chain.  
   Returns the length of the certificate.
   
   This isn't really a direct certificate function since the control flow 
   sequence is:

	import indirect: 
		GETNEXTCERT -> source object
			source object: 
				CREATEOBJECT_INDIRECT -> system device
					system device: createCertificate() 
		GETNEXTCERT -> source object
			source object: 
				CREATEOBJECT_INDIRECT -> system device
					system device: createCertificate() 
		[...]					

   however this seems to be the best place to put the code (sol lucet 
   omnibus) */

CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 4 ) ) \
int iCryptImportCertIndirect( OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,
							  IN_HANDLE const CRYPT_HANDLE iCertSource, 
							  IN_ENUM( CRYPT_KEYID ) \
								const CRYPT_KEYID_TYPE keyIDtype,
							  IN_BUFFER( keyIDlength ) const void *keyID, 
							  IN_LENGTH_SHORT const int keyIDlength,
							  IN_FLAGS_Z( KEYMGMT ) const int options )
	{
	assert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );
	assert( isReadPtr( keyID, keyIDlength ) );

	REQUIRES( isHandleRangeValid( iCertSource ) );
	REQUIRES( keyIDtype > CRYPT_KEYID_NONE && keyIDtype < CRYPT_KEYID_LAST );
	REQUIRES( keyIDlength > 0 && keyIDlength < MAX_INTLENGTH_SHORT );
	REQUIRES( options >= KEYMGMT_FLAG_NONE && options < KEYMGMT_FLAG_MAX && \
			  ( options & ~KEYMGMT_MASK_CERTOPTIONS ) == 0 );

	/* Clear return value */
	*iCertificate = CRYPT_ERROR;

	/* We're importing a sequence of certificates as a chain from a source 
	   object, assemble the collection via the object */
	return( assembleCertChain( iCertificate, iCertSource, keyIDtype, 
							   keyID, keyIDlength, options ) );
	}

/* Read a public key from an X.509 SubjectPublicKeyInfo record, creating the
   context necessary to contain it in the process.  Like the certificate 
   import function above this is another function of no fixed abode that 
   exists here because it's the least inappropriate location.
   
   The use of the void * instead of STREAM * is necessary because the STREAM
   type isn't visible at the global level */

CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int iCryptReadSubjectPublicKey( INOUT TYPECAST( STREAM * ) void *streamPtr, 
								OUT_HANDLE_OPT CRYPT_CONTEXT *iPubkeyContext,
								const BOOLEAN deferredLoad )
	{
	CRYPT_ALGO_TYPE cryptAlgo;
	CRYPT_CONTEXT iCryptContext;
	MESSAGE_CREATEOBJECT_INFO createInfo;
	MESSAGE_DATA msgData;
	STREAM *stream = streamPtr;
	void *spkiPtr = DUMMY_INIT_PTR;
	int length, spkiLength, status;

	assert( isReadPtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( iPubkeyContext, sizeof( CRYPT_CONTEXT ) ) );

	/* Clear return value */
	*iPubkeyContext = CRYPT_ERROR;

	/* Pre-parse the SubjectPublicKeyInfo, both to ensure that its valid 
	   before we go tothe extent of creating an encryption context to
	   contain it and to get access to the SubjectPublicKeyInfo data and
	   algorithm info.  Because all sorts of bizarre tagging exists due to 
	   things like CRMF we read the wrapper as a generic hole rather than 
	   the more obvious SEQUENCE.  The length values are only approximate 
	   because there's wrapper data involved and (for the maximum length) 
	   several of the DLP PKC values are only a fraction of 
	   CRYPT_MAX_PKCSIZE, the rest of the space requirement being allocated 
	   to the wrapper */
	status = getStreamObjectLength( stream, &spkiLength );
	if( cryptStatusOK( status ) )
		status = sMemGetDataBlock( stream, &spkiPtr, spkiLength );
	if( cryptStatusOK( status ) )
		status = readGenericHole( stream, NULL, 16, DEFAULT_TAG );
	if( cryptStatusError( status ) )
		return( status );
	if( spkiLength < 8 + MIN_PKCSIZE || \
		spkiLength > CRYPT_MAX_PKCSIZE * 4 )
		{
		/* If we're reading a certificate with a comically short public key 
		   we should try and return something a bit more informative than a 
		   generic bad-data error.  If we find a key like this we return 
		   an insecure-key error instead */
		if( isShortPKCKey( spkiLength - 8 ) )
			return( CRYPT_ERROR_NOSECURE );

		return( CRYPT_ERROR_BADDATA );
		}
	status = readAlgoIDparams( stream, &cryptAlgo, &length );
	if( cryptStatusOK( status ) && length > 0 )
		{
		/* There are algorithm parameters present, skip them */
		status = readUniversal( stream );
		}
	if( cryptStatusOK( status ) )
		{
		/* Read the public-key data */
		status = readUniversal( stream );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* Create the public-key context and send the public-key data to it */
	setMessageCreateObjectInfo( &createInfo, cryptAlgo );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  IMESSAGE_DEV_CREATEOBJECT, &createInfo, 
							  OBJECT_TYPE_CONTEXT );
	if( cryptStatusError( status ) )
		return( status );
	iCryptContext = createInfo.cryptHandle;
	setMessageData( &msgData, spkiPtr, spkiLength );
	status = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, 
							  &msgData, deferredLoad ? \
								CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL : \
								CRYPT_IATTRIBUTE_KEY_SPKI );
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
		return( status );
		}
	*iPubkeyContext = iCryptContext;
	assert( cryptStatusError( \
				krnlSendMessage( iCryptContext, IMESSAGE_CHECK, 
								 NULL, MESSAGE_CHECK_PKC_PRIVATE ) ) );
	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*						Certificate Management API Functions				*
*																			*
****************************************************************************/

/* Handle attribute data sent to or read from a certificate object.  We have
   to do this in a standalone function since it's called from several places
   in the certificate message handler */

CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 3 ) ) \
static int processCertAttribute( INOUT CERT_INFO *certInfoPtr,
								 IN_MESSAGE const MESSAGE_TYPE message,
								 INOUT void *messageDataPtr, 
								 IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )
	{
	MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;
	int *valuePtr = ( int * ) messageDataPtr;

	assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );

	REQUIRES( message == MESSAGE_GETATTRIBUTE || \
			  message == MESSAGE_GETATTRIBUTE_S || \
			  message == MESSAGE_SETATTRIBUTE || \
			  message == MESSAGE_SETATTRIBUTE_S || \
			  message == MESSAGE_DELETEATTRIBUTE );
	REQUIRES( isAttribute( attribute ) || \
			  isInternalAttribute( attribute ) );

	/* Process get/set/delete attribute messages */
	if( message == MESSAGE_GETATTRIBUTE )
		{
		int dummy;

		if( attribute == CRYPT_ATTRIBUTE_ERRORTYPE )
			{
			*valuePtr = certInfoPtr->errorType;
			return( CRYPT_OK );
			}
		if( attribute == CRYPT_ATTRIBUTE_ERRORLOCUS )
			{
			*valuePtr = certInfoPtr->errorLocus;
			return( CRYPT_OK );
			}
		return( getCertComponent( certInfoPtr, attribute, valuePtr, 
								  sizeof( int ), &dummy ) );
		}
	if( message == MESSAGE_GETATTRIBUTE_S )
		return( getCertComponent( certInfoPtr, attribute, 
								  msgData->data, msgData->length, 
								  &msgData->length ) );
	if( message == MESSAGE_SETATTRIBUTE )
		{
		BOOLEAN validCursorPosition;
		
		
		if( certInfoPtr->type == CRYPT_CERTTYPE_CMS_ATTRIBUTES )
			{
			validCursorPosition = \
				( attribute >= CRYPT_CERTINFO_FIRST_CMS && \
				  attribute <= CRYPT_CERTINFO_LAST_CMS ) ? TRUE : FALSE;
			}
		else
			{
			validCursorPosition = \
				( attribute >= CRYPT_CERTINFO_FIRST_EXTENSION && \
				  attribute <= CRYPT_CERTINFO_LAST_EXTENSION ) ? TRUE : FALSE;
			}

		/* If it's a completed certificate we can only add a restricted 
		   class of component selection control values to the object.  We
		   don't use continuation characters for the more complex isXYZ()
		   expressions because the resulting string is too long for some
		   broken compilers */
		REQUIRES( certInfoPtr->certificate == NULL || \
				  isDNSelectionComponent( attribute ) ||
				  isGeneralNameSelectionComponent( attribute ) || 
				  isCursorComponent( attribute ) || 
				  isControlComponent( attribute ) || 
				  attribute == CRYPT_IATTRIBUTE_INITIALISED || \
				  attribute == CRYPT_IATTRIBUTE_PKIUSERINFO );

		/* If it's an initialisation message, there's nothing to do (we get 
		   these when importing a certificate, when the import is complete 
		   the import code sends this message to move the cert into the high 
		   state because it's already signed) */
		if( attribute == CRYPT_IATTRIBUTE_INITIALISED )
			return( CRYPT_OK );

		/* If the passed-in value is a cursor-positioning code, make sure 
		   that it's valid */
		if( *valuePtr < 0 && *valuePtr != CRYPT_UNUSED && \
			( *valuePtr > CRYPT_CURSOR_FIRST || *valuePtr < CRYPT_CURSOR_LAST ) &&
			!validCursorPosition && attribute != CRYPT_CERTINFO_SELFSIGNED )
			return( CRYPT_ARGERROR_NUM1 );

		return( addCertComponent( certInfoPtr, attribute, valuePtr, 
								  CRYPT_UNUSED ) );
		}
	if( message == MESSAGE_SETATTRIBUTE_S )
		return( addCertComponent( certInfoPtr, attribute, msgData->data, 
								  msgData->length ) );
	if( message == MESSAGE_DELETEATTRIBUTE )
		return( deleteCertComponent( certInfoPtr, attribute ) );

	retIntError();
	}

/* Handle a message sent to a certificate context */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int certificateMessageFunction( INOUT TYPECAST( CERT_INFO * ) \
										void *objectInfoPtr,
									   IN_MESSAGE const MESSAGE_TYPE message,
									   void *messageDataPtr,
									   IN_INT_Z const int messageValue )
	{
	CERT_INFO *certInfoPtr = ( CERT_INFO * ) objectInfoPtr;

	assert( isWritePtr( objectInfoPtr, sizeof( CERT_INFO ) ) );

	REQUIRES( message > MESSAGE_NONE && message < MESSAGE_LAST );
	REQUIRES( ( message == MESSAGE_CRT_SIGCHECK && \
				messageValue == CRYPT_UNUSED ) || \
			  ( messageValue >= 0 && messageValue < MAX_INTLENGTH ) );

	/* Process destroy object messages */
	if( message == MESSAGE_DESTROY )
		{
		/* Clear the encoded certificate and miscellaneous components if
		   necessary.  Note that there's no need to clear the associated
		   encryption context (if any) since this is a dependent object of
		   the certificate and is destroyed by the kernel when the cert is 
		   destroyed */
		if( certInfoPtr->certificate != NULL )
			{
			zeroise( certInfoPtr->certificate, certInfoPtr->certificateSize );
			clFree( "certificateMessageFunction", certInfoPtr->certificate );
			}
		if( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
			certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \
			certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )
			{
			if( certInfoPtr->cCertCert->serialNumber != NULL && \
				certInfoPtr->cCertCert->serialNumber != \
					certInfoPtr->cCertCert->serialNumberBuffer )
				clFree( "certificateMessageFunction", 
						certInfoPtr->cCertCert->serialNumber );
			}
		if( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION )
			{
			if( certInfoPtr->cCertReq->serialNumber != NULL && \
				certInfoPtr->cCertReq->serialNumber != \
					certInfoPtr->cCertReq->serialNumberBuffer )
				clFree( "certificateMessageFunction", 
						certInfoPtr->cCertReq->serialNumber );
			}
		if( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE )
			{
			if( certInfoPtr->cCertCert->subjectUniqueID != NULL )
				clFree( "certificateMessageFunction", 
						certInfoPtr->cCertCert->subjectUniqueID );
			if( certInfoPtr->cCertCert->issuerUniqueID != NULL )
				clFree( "certificateMessageFunction", 
						certInfoPtr->cCertCert->issuerUniqueID );

⌨️ 快捷键说明

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