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

📄 certsign.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 4 页
字号:
											CRYPT_KEYUSAGE_CRLSIGN,
							complianceLevel, &certInfoPtr->errorLocus, 
							&certInfoPtr->errorType );
				if( cryptStatusError( status ) && \
					certInfoPtr->errorType == CRYPT_ERRTYPE_CONSTRAINT )
					/* If there was a constraint problem, it's something in 
					   the issuer's cert rather than the cert being signed 
					   so we have to change the error type accordingly.  
					   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( signatureLevel > CRYPT_SIGNATURELEVEL_NONE && \
		issuerCertInfoPtr != NULL )
		{
		assert( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT || \
				certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST );

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

			assert( signatureLevel == CRYPT_SIGNATURELEVEL_ALL );

			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->cCertCert->chainEnd )
			{
			for( i = 0; i < certInfoPtr->cCertCert->chainEnd; i++ )
				krnlSendNotifier( certInfoPtr->cCertCert->chain[ i ],
								  IMESSAGE_DECREFCOUNT );
			certInfoPtr->cCertCert->chainEnd = 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->cCertCert->chainEnd )
				{
				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->cCertRev->revocationTime <= 0 )
			certInfoPtr->cCertRev->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 );
			}
		}

	/* Determine the hash algorithm to use and, if it's a cert or CRL,
	   remember it for when we write the cert (the value is embedded in
	   the cert to prevent an obscure attack on unpadded RSA signature
	   algorithms) */
	krnlSendMessage( certInfoPtr->ownerHandle, IMESSAGE_GETATTRIBUTE, 
					 &hashAlgo, CRYPT_OPTION_ENCR_HASH );
	if( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
		certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN || \
		certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT )
		certInfoPtr->cCertCert->hashAlgo = hashAlgo;
	else
		if( certInfoPtr->type == CRYPT_CERTTYPE_CRL )
			certInfoPtr->cCertRev->hashAlgo = hashAlgo;

	/* 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 = \
				( signatureLevel == CRYPT_SIGNATURELEVEL_SIGNERCERT ) ? \
					( int ) sizeofObject( sizeofObject( extraDataLength ) ) : \
				( 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, 
							hashAlgo, formatInfo, extraDataEncodedLength );
		}
	else
		/* It's a standard signature */
		status = createX509signature( signedCertObject, 
							&signedCertObjectLength, signedCertAllocSize, 
							certObjectPtr, certObjectLength, signContext, 
							hashAlgo, 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( 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 0	/* 15/6/04 Only the root should be marked as self-signed, having 
				   supposedly self-signed certs inside the chain causes 
				   problems when trying to detect pathkludge certs */
	/* 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->cCertCert->chain[ certInfoPtr->cCertCert->chainEnd - 1 ], 
					IMESSAGE_GETATTRIBUTE, &selfSigned,
					CRYPT_CERTINFO_SELFSIGNED );
		if( cryptStatusOK( status ) && selfSigned )
			certInfoPtr->flags |= CERT_FLAG_SELFSIGNED;
		}
#endif /* 0 */

	/* 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 );

⌨️ 快捷键说明

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