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

📄 certsign.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:

	/* 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 
	   certificate 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 )
		{
		ENSURES( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT || \
				 certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST );

		if( signatureLevel == CRYPT_SIGNATURELEVEL_SIGNERCERT )
			{
			status = exportCert( NULL, 0, &extraDataLength,
								 CRYPT_CERTFORMAT_CERTIFICATE,
								 issuerCertInfoPtr );
			}
		else
			{
			MESSAGE_DATA msgData;

			ENSURES( 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( issuerCertAcquired )
				krnlReleaseObject( issuerCertInfoPtr->objectHandle );
			return( status );
			}
		}

	/* If it's a certificate chain copy over the signing certificate(s) */
	if( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )
		{
		status = copySigningCertChain( certInfoPtr, iSignContext );
		if( cryptStatusError( status ) )
			{
			if( issuerCertAcquired )
				krnlReleaseObject( issuerCertInfoPtr->objectHandle );
			return( status );
			}
		}

	/* Set up any required timestamps */
	status = setCertTimeinfo( certInfoPtr, iSignContext, isCertificate );
	if( cryptStatusError( status ) )
		{
		if( issuerCertAcquired )
			krnlReleaseObject( issuerCertInfoPtr->objectHandle );
		return( status );
		}

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

	/* Determine the hash algorithm to use and if it's a certificate or 
	   CRL remember it for when we write the certificate (the value is 
	   embedded in the certificate 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 */
	writeCertFunction = getCertWriteFunction( certInfoPtr->type );
	if( writeCertFunction == NULL )
		{
		if( issuerCertAcquired )
			krnlReleaseObject( issuerCertInfoPtr->objectHandle );
		retIntError();
		}

	/* Determine how big the encoded certificate information will be,
	   allocate memory for it and the full signed certificate, and write the
	   encoded certificate information */
	sMemNullOpen( &stream );
	status = writeCertFunction( &stream, certInfoPtr, issuerCertInfoPtr, 
								iSignContext );
	certObjectLength = stell( &stream );
	sMemClose( &stream );
	if( cryptStatusError( status ) )
		{
		if( issuerCertAcquired )
			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 && certObjectPtr != certObjectBuffer )
			clFree( "signCert", certObjectPtr );
		if( issuerCertAcquired )
			krnlReleaseObject( issuerCertInfoPtr->objectHandle );
		return( CRYPT_ERROR_MEMORY );
		}
	sMemOpen( &stream, certObjectPtr, certObjectLength );
	status = writeCertFunction( &stream, certInfoPtr, issuerCertInfoPtr, 
								iSignContext );
	ENSURES( cryptStatusError( status ) || \
			 certObjectLength == stell( &stream ) );
	sMemDisconnect( &stream );
	if( issuerCertAcquired )
		krnlReleaseObject( issuerCertInfoPtr->objectHandle );
	if( cryptStatusError( status ) )
		{
		zeroise( certObjectPtr, certObjectLength );
		if( certObjectPtr != certObjectBuffer )
			clFree( "signCert", certObjectPtr );
		clFree( "signCert", signedCertObject );
		return( status );
		}
	ENSURES( !cryptStatusError( checkObjectEncoding( certObjectPtr, \
													 certObjectLength ) ) );

	/* 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,
										signedCertAllocSize, certObjectPtr, 
										certObjectLength );
		zeroise( certObjectPtr, certObjectLength );
		if( certObjectPtr != certObjectBuffer )
			clFree( "signCert", certObjectPtr );
		ENSURES( !cryptStatusError( \
					checkObjectEncoding( certInfoPtr->certificate, \
										 certInfoPtr->certificateSize ) ) );
		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 )
		{
		X509SIG_FORMATINFO formatInfo;

		if( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT )
			{
			/* [1] SEQUENCE */
			setX509FormatInfo( &formatInfo, 1, FALSE );
			}
		else
			{
			/* [0] EXPLICIT SEQUENCE */
			setX509FormatInfo( &formatInfo, 0, TRUE );
			}
		if( signatureLevel == CRYPT_SIGNATURELEVEL_SIGNERCERT )
			{
			formatInfo.extraLength = ( int ) \
						sizeofObject( sizeofObject( extraDataLength ) );
			}
		else
			{
			if( signatureLevel == CRYPT_SIGNATURELEVEL_ALL )
				{
				formatInfo.extraLength = ( int ) \
						sizeofObject( extraDataLength );
				}
			}
		status = createX509signature( signedCertObject,
							signedCertAllocSize, &signedCertObjectLength, 
							certObjectPtr, certObjectLength, iSignContext,
							hashAlgo, &formatInfo );
		}
	else
		{
		/* It's a standard signature */
		status = createX509signature( signedCertObject,
							signedCertAllocSize, &signedCertObjectLength, 
							certObjectPtr, certObjectLength, iSignContext,
							hashAlgo, NULL );
		}
	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 signature */
	if( extraDataLength > 0 )
		{
		const int extraDataType = \
			( signatureLevel == CRYPT_SIGNATURELEVEL_SIGNERCERT ) ? \
			CRYPT_CERTFORMAT_CERTIFICATE : CRYPT_ICERTFORMAT_CERTSEQUENCE;

		sMemOpen( &stream, ( BYTE * ) signedCertObject + signedCertObjectLength,
				  signedCertAllocSize - signedCertObjectLength );
		if( signatureLevel == CRYPT_SIGNATURELEVEL_SIGNERCERT )
			{
			writeConstructed( &stream, sizeofObject( extraDataLength ), 0 );
			writeSequence( &stream, extraDataLength );
			}
		else
			{
			ENSURES( signatureLevel == CRYPT_SIGNATURELEVEL_ALL );

			writeConstructed( &stream, extraDataLength, 0 );
			}
		status = exportCertToStream( &stream, issuerCertInfoPtr->objectHandle,
									 extraDataType );
		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 );
			}
		}
	ENSURES( !cryptStatusError( \
				checkObjectEncoding( certInfoPtr->certificate, \
									 certInfoPtr->certificateSize ) ) );

	/* If it's a certification request it's now self-signed.  In addition 
	   the signature has been checked since we've 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 certificates inside the chain 
				   causes problems when trying to detect pathkludge 
				   certificates */
	/* If it's a certificate chain and the root is self-signed then 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 );

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

⌨️ 快捷键说明

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