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

📄 certsign.c

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

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

	REQUIRES( iSignContext == CRYPT_UNUSED || \
			  isHandleRangeValid( iSignContext ) );

	/* 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 <= MIN_TIME_VALUE )
		{
		/* 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 <= MIN_TIME_VALUE )
		{
		int validity;

		status = krnlSendMessage( certInfoPtr->ownerHandle, 
								  IMESSAGE_GETATTRIBUTE, &validity, 
								  CRYPT_OPTION_CERT_VALIDITY );
		if( cryptStatusError( status ) )
			return( status );
		certInfoPtr->endTime = certInfoPtr->startTime + \
							   ( ( time_t ) validity * 86400L );
		}
	if( certInfoPtr->type == CRYPT_CERTTYPE_CRL || \
		certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE )
		{
		if( certInfoPtr->endTime <= MIN_TIME_VALUE )
			{
			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;

				status = krnlSendMessage( certInfoPtr->ownerHandle,
										  IMESSAGE_GETATTRIBUTE, &updateInterval,
										  CRYPT_OPTION_CERT_UPDATEINTERVAL );
				if( cryptStatusError( status ) )
					return( status );
				certInfoPtr->endTime = certInfoPtr->startTime + \
									   ( ( time_t ) updateInterval * 86400L );
				}
			}
		if( certInfoPtr->cCertRev->revocationTime <= MIN_TIME_VALUE )
			certInfoPtr->cCertRev->revocationTime = currentTime;
		}

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*								Signing Functions							*
*																			*
****************************************************************************/

/* Pseudo-sign certificate information by writing the outer wrapper and
   moving the object into the initialised state */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
static int pseudoSignCertificate( INOUT CERT_INFO *certInfoPtr,
								  INOUT_BUFFER_FIXED( signedCertObjectMaxLength ) \
										void *signedCertObject,
								  IN_LENGTH_SHORT_MIN( 16 ) \
										const int signedCertObjectMaxLength,
								  IN_BUFFER( certObjectLength ) \
										const void *certObject,
								  IN_LENGTH_SHORT_MIN( 16 ) \
										const int certObjectLength )
	{
	STREAM stream;
	int signedCertObjectLength, status;

	assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );
	assert( isWritePtr( signedCertObject, signedCertObjectMaxLength ) );
	assert( isReadPtr( certObject, certObjectLength ) );

	REQUIRES( signedCertObjectMaxLength >= 16 && \
			  signedCertObjectMaxLength < MAX_INTLENGTH_SHORT );
	REQUIRES( certObjectLength >= 16 && \
			  certObjectLength <= signedCertObjectMaxLength && \
			  certObjectLength < MAX_INTLENGTH_SHORT );

	switch( certInfoPtr->type )
		{
		case CRYPT_CERTTYPE_OCSP_REQUEST:
		case CRYPT_CERTTYPE_PKIUSER:
			/* It's an unsigned OCSP request or PKI user info, write the
			   outer wrapper */
			signedCertObjectLength = sizeofObject( certObjectLength );
			ENSURES( signedCertObjectLength <= signedCertObjectMaxLength );
			sMemOpen( &stream, signedCertObject, signedCertObjectLength );
			writeSequence( &stream, certObjectLength );
			status = swrite( &stream, certObject, certObjectLength );
			ENSURES( cryptStatusOK( status ) );
			sMemDisconnect( &stream );
			if( certInfoPtr->type == CRYPT_CERTTYPE_PKIUSER )
				{
				status = recoverCertData( certInfoPtr, 
										  CRYPT_CERTTYPE_PKIUSER, 
										  signedCertObject,
										  signedCertObjectLength );
				if( cryptStatusError( status ) )
					return( status );
				}
			break;

		case CRYPT_CERTTYPE_RTCS_REQUEST:
		case CRYPT_CERTTYPE_RTCS_RESPONSE:
		case CRYPT_CERTTYPE_OCSP_RESPONSE:
			/* It's an RTCS request/response or OCSP response, it's already
			   in the form required */
			signedCertObjectLength = certObjectLength;
			ENSURES( signedCertObjectLength <= signedCertObjectMaxLength );
			memcpy( signedCertObject, certObject, certObjectLength );
			break;

		case CRYPT_CERTTYPE_REQUEST_CERT:
			{
			const int dataSize = certObjectLength + \
								 sizeofObject( sizeofShortInteger( 0 ) );

			ENSURES( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT );

			/* It's an encryption-only key, wrap up the certificate data 
			   with an indication that private key POP will be performed via 
			   out-of-band means and remember where the encoded data 
			   starts */
			signedCertObjectLength = sizeofObject( dataSize );
			ENSURES( signedCertObjectLength <= signedCertObjectMaxLength );
			sMemOpen( &stream, signedCertObject, signedCertObjectLength );
			writeSequence( &stream, dataSize );
			swrite( &stream, certObject, certObjectLength );
			writeConstructed( &stream, sizeofShortInteger( 0 ), 2 );
			status = writeShortInteger( &stream, 0, 1 );
			ENSURES( cryptStatusOK( status ) );
			sMemDisconnect( &stream );
			status = recoverCertData( certInfoPtr, 
									  CRYPT_CERTTYPE_REQUEST_CERT,
									  signedCertObject,
									  signedCertObjectLength );
			if( cryptStatusError( status ) )
				return( status );

			/* The pseudo-signature has been checked (since we just created
			   it), this also avoids nasty semantic problems with not-really-
			   signed CRMF requests with encryption-only keys */
			certInfoPtr->flags |= CERT_FLAG_SELFSIGNED;
			break;
			}

		case CRYPT_CERTTYPE_REQUEST_REVOCATION:
			/* Revocation requests can't be signed so the (pseudo-)signed
			   data is just the object data */
			signedCertObjectLength = certObjectLength;
			ENSURES( signedCertObjectLength <= signedCertObjectMaxLength );
			memcpy( signedCertObject, certObject, certObjectLength );

			/* Since revocation requests can't be signed we mark them as
			   pseudo-signed to avoid any problems that might arise from
			   this */
			certInfoPtr->flags |= CERT_FLAG_SELFSIGNED;
			break;

		default:
			retIntError();
		}
	certInfoPtr->certificate = signedCertObject;
	certInfoPtr->certificateSize = signedCertObjectLength;

	/* The object is now (pseudo-)signed and initialised */
	certInfoPtr->flags |= CERT_FLAG_SIGCHECKED;
	if( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT )
		{
		/* If it's a CRMF request with POP done via out-of-band means we
		   got here via a standard signing action (except that the key was
		   an encryption-only key), don't change the object state since the
		   kernel will do this as the post-signing step */
		return( CRYPT_OK );
		}
	return( krnlSendMessage( certInfoPtr->objectHandle,
							 IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_UNUSED,
							 CRYPT_IATTRIBUTE_INITIALISED ) );
	}

/* Sign a certificate object */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int signCert( INOUT CERT_INFO *certInfoPtr, 
			  IN_HANDLE_OPT const CRYPT_CONTEXT iSignContext )
	{
	CRYPT_ALGO_TYPE hashAlgo;
	CERT_INFO *issuerCertInfoPtr = NULL;
	STREAM stream;
	WRITECERT_FUNCTION writeCertFunction;
	const CRYPT_SIGNATURELEVEL_TYPE signatureLevel = \
				( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST ) ? \
					certInfoPtr->cCertRev->signatureLevel : \
					CRYPT_SIGNATURELEVEL_NONE;
	const BOOLEAN isCertificate = \
			( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
			  certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \
			  certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN ) ? TRUE : FALSE;
	BOOLEAN issuerCertAcquired = FALSE, nonSigningKey = FALSE;
	BYTE certObjectBuffer[ 1024 + 8 ], *certObjectPtr = certObjectBuffer;
	void *signedCertObject;
	int certObjectLength, signedCertObjectLength, signedCertAllocSize;
	int extraDataLength = 0, complianceLevel, status;

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

	REQUIRES( iSignContext == CRYPT_UNUSED || \
			  isHandleRangeValid( iSignContext ) );
	REQUIRES( certInfoPtr->certificate == NULL );

	/* Determine how much checking we need to perform */
	status = krnlSendMessage( certInfoPtr->ownerHandle,
							  IMESSAGE_GETATTRIBUTE, &complianceLevel,
							  CRYPT_OPTION_CERT_COMPLIANCELEVEL );
	if( cryptStatusError( status ) )
		return( status );

	/* If it's a non-signing key we have to create a special format of 
	   certificate request that isn't signed but contains an indication that 
	   the private key POP will be performed by out-of-band means.  We also 
	   have to check for the iSignContext being absent to handle OCSP 
	   requests for which the signature is optional so there may be no 
	   signing key present */
	if( iSignContext == CRYPT_UNUSED || \
		cryptStatusError( krnlSendMessage( iSignContext, IMESSAGE_CHECK,
						  NULL, MESSAGE_CHECK_PKC_SIGN ) ) )
		nonSigningKey = TRUE;

	/* Obtain the issuer certificate from the private key if necessary */
	if( isCertificate || certInfoPtr->type == CRYPT_CERTTYPE_CRL || \
		( ( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST || \
			certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE ) && \
		  !nonSigningKey ) )
		{
		/* If it's a self-signed certificate then the issuer is also the 
		   subject */
		if( certInfoPtr->flags & CERT_FLAG_SELFSIGNED )
			issuerCertInfoPtr = certInfoPtr;
		else
			{
			CRYPT_CERTIFICATE dataOnlyCert;

			/* Get the data-only certificate from the context */
			status = krnlSendMessage( iSignContext, IMESSAGE_GETDEPENDENT,
									  &dataOnlyCert, OBJECT_TYPE_CERTIFICATE );
			if( cryptStatusError( status ) )
				return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
						CRYPT_ARGERROR_VALUE : status );
			status = krnlAcquireObject( dataOnlyCert, OBJECT_TYPE_CERTIFICATE,
										( void ** ) &issuerCertInfoPtr,
										CRYPT_ARGERROR_VALUE );
			if( cryptStatusError( status ) )
				return( status );
			issuerCertAcquired = TRUE;
			}

		/* Check the signing key */
		status = checkSigningKey( certInfoPtr, issuerCertInfoPtr, 
								  isCertificate, complianceLevel );
		if( cryptStatusError( status ) )
			{
			if( issuerCertAcquired )
				krnlReleaseObject( issuerCertInfoPtr->objectHandle );
			return( status );
			}
		}

⌨️ 快捷键说明

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