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

📄 certsig.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:
					   What's reported isn't strictly accurate since the 
					   locus is in the issuer rather than subject cert, but 
					   it's the best we can do */
					certInfoPtr->errorType = CRYPT_ERRTYPE_ISSUERCONSTRAINT;
				}
		if( cryptStatusError( status ) )
			{
			if( issuerCertPresent )
				krnlReleaseObject( issuerCertInfoPtr->objectHandle );
			return( status );
			}
		}

	/* If we need to include extra data in the signature, make sure that it's
	   available and determine how big it'll be.  If there's no issuer cert
	   available and we've been asked for extra signature data, we fall back 
	   to providing just a raw signature rather than bailing out completely */
	if( certInfoPtr->signatureLevel > CRYPT_SIGNATURELEVEL_NONE && \
		issuerCertInfoPtr != NULL )
		{
		assert( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT || \
				certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST );

		if( certInfoPtr->signatureLevel == CRYPT_SIGNATURELEVEL_SIGNERCERT )
			status = exportCert( NULL, &extraDataLength,
								 CRYPT_CERTFORMAT_CERTIFICATE, 
								 issuerCertInfoPtr, CRYPT_UNUSED );
		else
			{
			RESOURCE_DATA msgData;

			setMessageData( &msgData, NULL, 0 );
			status = krnlSendMessage( issuerCertInfoPtr->objectHandle, 
									  IMESSAGE_CRT_EXPORT, &msgData, 
									  CRYPT_ICERTFORMAT_CERTSEQUENCE );
			extraDataLength = msgData.length;
			}
		if( cryptStatusError( status ) )
			{
			if( issuerCertPresent )
				krnlReleaseObject( issuerCertInfoPtr->objectHandle );
			return( status );
			}
		}

	/* If it's a certificate chain, copy over the signing cert(s) */
	if( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )
		{
		/* If there's a chain of certs present (for example from a previous
		   signing attempt that wasn't completed due to an error), free
		   them */
		if( certInfoPtr->certChainEnd )
			{
			for( i = 0; i < certInfoPtr->certChainEnd; i++ )
				krnlSendNotifier( certInfoPtr->certChain[ i ],
								  IMESSAGE_DECREFCOUNT );
			certInfoPtr->certChainEnd = 0;
			}

		/* If it's a self-signed cert, it must be the only cert in the chain
		   (creating a chain like this doesn't make much sense, but we handle
		   it anyway) */
		if( certInfoPtr->flags & CERT_FLAG_SELFSIGNED )
			{
			if( certInfoPtr->certChainEnd )
				{
				setErrorInfo( certInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
							  CRYPT_ERRTYPE_ATTR_PRESENT );
				status = CRYPT_ERROR_INVALID;
				}
			}
		else
			/* Copy the cert chain into the cert to be signed */
			status = copyCertChain( certInfoPtr, signContext, FALSE );
		if( cryptStatusError( status ) )
			{
			if( issuerCertPresent )
				krnlReleaseObject( issuerCertInfoPtr->objectHandle );
			return( status );
			}
		}

	/* If it's some certificate variant or CRL/OCSP response and the various 
	   timestamps haven't been set yet, start them at the current time and 
	   give them the default validity period or next update time if these 
	   haven't been set.  The time used is the local time, this is converted 
	   to GMT when we write it to the certificate.  Issues like validity 
	   period nesting and checking for valid time periods are handled 
	   elsewhere */
	if( ( isCertificate || certInfoPtr->type == CRYPT_CERTTYPE_CRL || \
		  certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE ) && \
		certInfoPtr->startTime <= 0 )
		{
		/* If the time is screwed up we can't provide a signed indication
		   of the time */
		if( currentTime < MIN_TIME_VALUE )
			{
			setErrorInfo( certInfoPtr, CRYPT_CERTINFO_VALIDFROM,
						  CRYPT_ERRTYPE_ATTR_VALUE );
			return( CRYPT_ERROR_NOTINITED );
			}
		certInfoPtr->startTime = currentTime;
		}
	if( isCertificate && certInfoPtr->endTime <= 0 )
		{
		int validity;

		krnlSendMessage( certInfoPtr->ownerHandle, IMESSAGE_GETATTRIBUTE, 
						 &validity, CRYPT_OPTION_CERT_VALIDITY );
		certInfoPtr->endTime = certInfoPtr->startTime + \
							   ( ( time_t ) validity * 86400L );
		}
	if( certInfoPtr->type == CRYPT_CERTTYPE_CRL || \
		certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE )
		{
		if( certInfoPtr->endTime <= 0 )
			{
			if( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE )
				/* OCSP responses come directly from the certificate store
				   and represent an atomic (and ephemeral) snapshot of the 
				   store state.  Because of this the next-update time is
				   effectively immediately, since the next snapshot could
				   provide a different response */
				certInfoPtr->endTime = currentTime;
			else
				{
				int updateInterval;

				krnlSendMessage( certInfoPtr->ownerHandle, 
								 IMESSAGE_GETATTRIBUTE, &updateInterval, 
								 CRYPT_OPTION_CERT_UPDATEINTERVAL );

				certInfoPtr->endTime = certInfoPtr->startTime + \
									   ( ( time_t ) updateInterval * 86400L );
				}
			}
		if( certInfoPtr->revocationTime <= 0 )
			certInfoPtr->revocationTime = currentTime;
		}

	/* If it's a certificate, set up the certificate serial number */
	if( isCertificate )
		{
		status = setSerialNumber( certInfoPtr, NULL, 0 );
		if( cryptStatusError( status ) )
			{
			if( issuerCertPresent )
				krnlReleaseObject( issuerCertInfoPtr->objectHandle );
			return( status );
			}
		}

	/* Select the function to use to write the certificate object to be
	   signed */
	for( i = 0; certWriteTable[ i ].type != certInfoPtr->type && \
				certWriteTable[ i ].type != CRYPT_CERTTYPE_NONE; i++ );
	if( certWriteTable[ i ].type == CRYPT_CERTTYPE_NONE )
		{
		assert( NOTREACHED );
		return( CRYPT_ERROR_NOTAVAIL );
		}
	writeCertObjectFunction = certWriteTable[ i ].writeFunction;

	/* Determine how big the encoded certificate information will be,
	   allocate memory for it and the full signed certificate, and write the
	   encoded certificate information */
	sMemOpen( &stream, NULL, 0 );
	status = writeCertObjectFunction( &stream, certInfoPtr, issuerCertInfoPtr,
									  signContext );
	certObjectLength = stell( &stream );
	sMemClose( &stream );
	if( cryptStatusError( status ) )
		{
		if( issuerCertPresent )
			krnlReleaseObject( issuerCertInfoPtr->objectHandle );
		return( status );
		}
	signedCertAllocSize = certObjectLength + 1024 + extraDataLength;
	if( ( certObjectLength > 1024 && \
		  ( certObjectPtr = clDynAlloc( "signCert", \
										certObjectLength ) ) == NULL ) || \
		( signedCertObject = clAlloc( "signCert", \
									  signedCertAllocSize ) ) == NULL )
		{
		if( certObjectPtr != NULL )
			clFree( "signCert", certObjectPtr );
		if( issuerCertPresent )
			krnlReleaseObject( issuerCertInfoPtr->objectHandle );
		return( CRYPT_ERROR_MEMORY );
		}
	sMemOpen( &stream, certObjectPtr, certObjectLength );
	status = writeCertObjectFunction( &stream, certInfoPtr, issuerCertInfoPtr,
									  signContext );
	assert( certObjectLength == stream.bufPos );
	sMemDisconnect( &stream );
	if( issuerCertPresent )
		krnlReleaseObject( issuerCertInfoPtr->objectHandle );
	if( cryptStatusError( status ) )
		{
		zeroise( certObjectPtr, certObjectLength );
		if( certObjectPtr != certObjectBuffer )
			clFree( "signCert", certObjectPtr );
		clFree( "signCert", signedCertObject );
		return( status );
		}

	/* If there's no signing key present, pseudo-sign the certificate 
	   information by writing the outer wrapper and moving the object into
	   the initialised state */
	if( nonSigningKey )
		{
		status = pseudoSignCertificate( certInfoPtr, signedCertObject, 
										certObjectPtr, certObjectLength );
		zeroise( certObjectPtr, certObjectLength );
		if( certObjectPtr != certObjectBuffer )
			clFree( "signCert", certObjectPtr );
		return( status );
		}

	/* Sign the certificate information.  CRMF and OCSP use a b0rken 
	   signature format (the authors couldn't quite manage a cut & paste of 
	   two lines of text), so if it's one of these we have to use nonstandard 
	   formatting */
	if( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT || \
		certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST )
		{
		const int extraDataEncodedLength = \
				( certInfoPtr->signatureLevel == \
							CRYPT_SIGNATURELEVEL_SIGNERCERT ) ? \
					( int ) sizeofObject( sizeofObject( extraDataLength ) ) : \
				( certInfoPtr->signatureLevel == \
							CRYPT_SIGNATURELEVEL_ALL ) ? \
					( int ) sizeofObject( extraDataLength ) : 0;
		const int formatInfo = \
				( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT ) ? \
				1 : ( 0 | 0x80 );

		status = createX509signature( signedCertObject, 
							&signedCertObjectLength, signedCertAllocSize,
							certObjectPtr, certObjectLength, signContext, 
							CRYPT_ALGO_SHA, formatInfo, 
							extraDataEncodedLength );
		}
	else
		/* It's a standard signature */
		status = createX509signature( signedCertObject, 
							&signedCertObjectLength, signedCertAllocSize, 
							certObjectPtr, certObjectLength, signContext, 
							CRYPT_ALGO_SHA, CRYPT_UNUSED, 0 );
	zeroise( certObjectPtr, certObjectLength );
	if( certObjectPtr != certObjectBuffer )
		clFree( "signCert", certObjectPtr );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_NUM1 ) ? \
				CRYPT_ARGERROR_VALUE : status );
	certInfoPtr->certificate = signedCertObject;
	certInfoPtr->certificateSize = signedCertObjectLength;

	/* If we need to include extra data with the signature, attach it to the
	   end of the sig */
	if( extraDataLength > 0 )
		{
		sMemOpen( &stream, ( BYTE * ) signedCertObject + signedCertObjectLength, 
				  signedCertAllocSize - signedCertObjectLength );
		if( certInfoPtr->signatureLevel == \
								CRYPT_SIGNATURELEVEL_SIGNERCERT )
			{
			writeConstructed( &stream, sizeofObject( extraDataLength ), 0 );
			writeSequence( &stream, extraDataLength );
			assert( sStatusOK( &stream ) && \
					sMemDataLeft( &stream ) >= extraDataLength );
			status = exportCert( sMemBufPtr( &stream ), &extraDataLength,
								 CRYPT_CERTFORMAT_CERTIFICATE, 
								 issuerCertInfoPtr, sMemDataLeft( &stream ) );
			}
		else
			{
			writeConstructed( &stream, extraDataLength, 0 );
			assert( sStatusOK( &stream ) && \
					sMemDataLeft( &stream ) >= extraDataLength );
			status = exportCertToStream( &stream, 
										 issuerCertInfoPtr->objectHandle,
										 CRYPT_ICERTFORMAT_CERTSEQUENCE );
			}
		certInfoPtr->certificateSize = signedCertObjectLength + \
									   stell( &stream );
		sMemDisconnect( &stream );
		if( cryptStatusError( status ) )
			{
			zeroise( certInfoPtr->certificate, signedCertAllocSize );
			clFree( "signCert", certInfoPtr->certificate );
			certInfoPtr->certificate = NULL;
			certInfoPtr->certificateSize = 0;
			return( status );
			}
		}

	/* If it's a certification request, it's now self-signed.  In addition 
	   the signature has been checked, since we just created it */
	if( certInfoPtr->type == CRYPT_CERTTYPE_CERTREQUEST || \
		certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT )
		certInfoPtr->flags |= CERT_FLAG_SELFSIGNED;
	certInfoPtr->flags |= CERT_FLAG_SIGCHECKED;

	/* If it's a cert chain and the root is self-signed, the entire chain 
	   counts as self-signed */
	if( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )
		{
		int selfSigned;

		status = krnlSendMessage( \
						certInfoPtr->certChain[ certInfoPtr->certChainEnd - 1 ], 
						IMESSAGE_GETATTRIBUTE, &selfSigned,
						CRYPT_CERTINFO_SELFSIGNED );
		if( cryptStatusOK( status ) && selfSigned )
			certInfoPtr->flags |= CERT_FLAG_SELFSIGNED;
		}

	/* If it's not an object type with special-case post-signing 
	   requirements, we're done */
	if( certInfoPtr->type != CRYPT_CERTTYPE_CERTIFICATE && \
		certInfoPtr->type != CRYPT_CERTTYPE_CERTCHAIN && \
		certInfoPtr->type != CRYPT_CERTTYPE_REQUEST_CERT )
		return( CRYPT_OK );

	/* Recover information such as pointers to encoded cert data */
	return( recoverCertData( certInfoPtr, signedCertObject, 
							 signedCertObjectLength, certInfoPtr->type ) );
	}

/****************************************************************************
*																			*
*							Certificate Checking Functions					*
*																			*
****************************************************************************/

/* Generate a nameID or issuerID.  These are needed when storing/retrieving a
   cert to/from an database keyset, which can't handle the awkward 
   heirarchical IDs usually used in certs.  There are two types of IDs, the 
   nameID, which is an SHA-1 hash of the DN and is used for certs, and the 

⌨️ 快捷键说明

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