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

📄 comp_set.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 5 页
字号:
		}

	/* Copy across the canonicalised serial number value */
	if( length >= SERIALNO_BUFSIZE && \
		( serialNumberPtr = clDynAlloc( "setSerialNumber", length ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	if( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION )
		{
		certInfoPtr->cCertReq->serialNumber = serialNumberPtr;
		certInfoPtr->cCertReq->serialNumberLength = length;
		}
	else
		{
		certInfoPtr->cCertCert->serialNumber = serialNumberPtr;
		certInfoPtr->cCertCert->serialNumberLength = length;
		}
	memcpy( serialNumberPtr, buffer + bufPos, length );

	return( CRYPT_OK );
	}

/* Compare a serial number in canonical form to a generic serial number, 
   with special handling for leading-zero truncation.  This one can get a 
   bit tricky because Microsoft fairly consistently encode the serial 
   numbers incorrectly, so we normalise the values to have no leading zero, 
   which is the lowest common denominator */

int compareSerialNumber( const void *canonSerialNumber, 
						 const int canonSerialNumberLength,
						 const void *serialNumber, 
						 const int serialNumberLength )
	{
	const BYTE *canonSerialNumberPtr = canonSerialNumber;
	const BYTE *serialNumberPtr = serialNumber;
	int canonSerialLength = canonSerialNumberLength;
	int serialLength = serialNumberLength;

	/* Internal serial numbers are canonicalised, so all we need to do is
	   strip a possible leading zero */
	if( !canonSerialNumberPtr[ 0 ] )
		{
		canonSerialNumberPtr++;
		canonSerialLength--;
		}
	assert( canonSerialLength == 0 || canonSerialNumberPtr[ 0 ] );

	/* Serial numbers from external sources can be arbitarily strangely 
	   encoded, so we strip leading zeroes until we get to actual data */
	while( serialLength > 0 && !serialNumberPtr[ 0 ] )
		{
		serialNumberPtr++;
		serialLength--;
		}

	/* Finally we've got them in a form where we can compare them */
	if( canonSerialLength != serialLength || \
		memcmp( canonSerialNumberPtr, serialNumberPtr, serialLength ) )
		return( 1 );

	return( 0 );
	}

/****************************************************************************
*																			*
*								Copy Cert Info								*
*																			*
****************************************************************************/

/* Copy public key data into a certificate object */

static int copyPublicKeyInfo( CERT_INFO *certInfoPtr,
							  const CRYPT_HANDLE cryptHandle,
							  const CERT_INFO *srcCertInfoPtr )
	{
	void *publicKeyInfoPtr;
	int length, status;

	assert( ( isHandleRangeValid( cryptHandle ) && srcCertInfoPtr == NULL ) || \
			( !isHandleRangeValid( cryptHandle ) && srcCertInfoPtr != NULL ) );

	/* Make sure that we haven't already got a public key present */
	if( certInfoPtr->iPubkeyContext != CRYPT_ERROR || \
		certInfoPtr->publicKeyInfo != NULL )
		{
		setErrorInfo( certInfoPtr, CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO,
					  CRYPT_ERRTYPE_ATTR_PRESENT );
		return( CRYPT_ERROR_INITED );
		}

	/* If we've been given a data-only cert, copy over the public key data */
	if( srcCertInfoPtr != NULL )
		{
		assert( srcCertInfoPtr->publicKeyAlgo > CRYPT_ALGO_NONE );
		assert( memcmp( srcCertInfoPtr->publicKeyID,
						"\x00\x00\x00\x00\x00\x00\x00\x00", 8 ) );
		assert( ( ( BYTE * ) srcCertInfoPtr->publicKeyInfo )[ 0 ] == 0x30 );

		length = srcCertInfoPtr->publicKeyInfoSize;
		if( ( publicKeyInfoPtr = clAlloc( "copyPublicKeyInfo", length ) ) == NULL )
			return( CRYPT_ERROR_MEMORY );
		memcpy( publicKeyInfoPtr, srcCertInfoPtr->publicKeyInfo, length );
		certInfoPtr->publicKeyAlgo = srcCertInfoPtr->publicKeyAlgo;
		certInfoPtr->publicKeyFeatures = srcCertInfoPtr->publicKeyFeatures;
		memcpy( certInfoPtr->publicKeyID, srcCertInfoPtr->publicKeyID,
				KEYID_SIZE );
		}
	else
		{
		CRYPT_CONTEXT iCryptContext;
		RESOURCE_DATA msgData;

		/* Get the context handle.  All other checking has already been
		   performed by the kernel */
		status = krnlSendMessage( cryptHandle, IMESSAGE_GETDEPENDENT,
								  &iCryptContext, OBJECT_TYPE_CONTEXT );
		if( cryptStatusError( status ) )
			{
			setErrorInfo( certInfoPtr, CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO,
						  CRYPT_ERRTYPE_ATTR_VALUE );
			return( status );
			}
		assert( cryptStatusOK( \
					krnlSendMessage( iCryptContext, IMESSAGE_CHECK, NULL,
									 MESSAGE_CHECK_PKC ) ) );

		/* Get the key information */
		status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,
								  &certInfoPtr->publicKeyAlgo,
								  CRYPT_CTXINFO_ALGO );
		if( cryptStatusOK( status ) )
			status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,
									  &certInfoPtr->publicKeyFeatures,
									  CRYPT_IATTRIBUTE_KEYFEATURES );
		if( cryptStatusOK( status ) )
			{
			setMessageData( &msgData, certInfoPtr->publicKeyID, KEYID_SIZE );
			status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,
									  &msgData, CRYPT_IATTRIBUTE_KEYID );
			}
		if( cryptStatusError( status ) )
			return( status );

		/* Copy over the public-key data.  We copy the data rather than
		   keeping a reference to the context for two reasons.  Firstly,
		   when the cert is transitioned into the high state it will
		   constrain the attached context, so a context shared between two
		   certs could be constrained in unexpected ways.  Secondly, the
		   context could be a private-key context, and attaching that to a
		   cert would be rather inappropriate.  Furthermore, the constraint
		   issue is even more problematic in that a context constrained by
		   an encryption-only request could then no longer be used to sign
		   the request or a PKI protocol message containing the request */
		setMessageData( &msgData, NULL, 0 );
		status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_IATTRIBUTE_KEY_SPKI );
		if( cryptStatusOK( status ) )
			{
			length = msgData.length;
			if( ( publicKeyInfoPtr = clAlloc( "copyPublicKeyInfo",
											  length ) ) == NULL )
				status = CRYPT_ERROR_MEMORY;
			}
		if( cryptStatusError( status ) )
			return( status );
		msgData.data = publicKeyInfoPtr;
		status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_IATTRIBUTE_KEY_SPKI );
		if( cryptStatusError( status ) )
			return( status );
		}
	certInfoPtr->publicKeyData = certInfoPtr->publicKeyInfo = \
		publicKeyInfoPtr;
	certInfoPtr->publicKeyInfoSize = length;
	certInfoPtr->flags |= CERT_FLAG_DATAONLY;

	return( CRYPT_OK );
	}

/* Copy cert request info into a certificate object.  This copies the public
   key context, the DN, any valid attributes, and any other relevant bits and
   pieces if it's a CRMF request */

static int copyCertReqInfo( CERT_INFO *certInfoPtr,
							CERT_INFO *certRequestInfoPtr )
	{
	int status;

	assert( certRequestInfoPtr->type == CRYPT_CERTTYPE_CERTREQUEST || \
			certRequestInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT );

	/* Copy the public key context, the DN, and the attributes.  Type
	   checking has already been performed by the kernel.  We copy the
	   attributes across after the DN because that copy is the hardest to
	   undo: If there are already attributes present, the copied attributes
	   will be mixed in among them so it's not really possible to undo the
	   copy later without performing a complex selective delete */
	status = copyDN( &certInfoPtr->subjectName,
					 certRequestInfoPtr->subjectName );
	if( cryptStatusOK( status ) )
		{
		if( certRequestInfoPtr->flags & CERT_FLAG_DATAONLY )
			status = copyPublicKeyInfo( certInfoPtr, CRYPT_UNUSED,
										certRequestInfoPtr );
		else
			status = copyPublicKeyInfo( certInfoPtr,
										certRequestInfoPtr->iPubkeyContext,
										NULL );
		}
	if( cryptStatusOK( status ) && \
		certRequestInfoPtr->attributes != NULL )
		{
		status = copyAttributes( &certInfoPtr->attributes,
								 certRequestInfoPtr->attributes,
								 &certInfoPtr->errorLocus,
								 &certInfoPtr->errorType );
		if( cryptStatusError( status ) )
			deleteDN( &certInfoPtr->subjectName );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* If it's a CRMF request there could also be a validity period
	   specified */
	if( certRequestInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT )
		{
		const time_t currentTime = getApproxTime();

		/* We don't allow start times backdated by more than a year, or end
		   times before the start time.  Since these are trivial things, we
		   don't abort if there's a problem but just quietly fix the value */
		if( certRequestInfoPtr->startTime > 0 && \
			certRequestInfoPtr->startTime > currentTime - ( 86400 * 365 ) )
			certInfoPtr->startTime = certRequestInfoPtr->startTime;
		if( certRequestInfoPtr->endTime > 0 && \
			certRequestInfoPtr->endTime > certInfoPtr->startTime )
			certInfoPtr->endTime = certRequestInfoPtr->endTime;
		}

	return( CRYPT_OK );
	}

/* Copy what we need to identify the cert to be revoked and any revocation
   information into a certificate object */

static int copyRevReqInfo( CERT_INFO *certInfoPtr,
						   CERT_INFO *revRequestInfoPtr )
	{
	int status;

	status = copyRevocationInfo( certInfoPtr, revRequestInfoPtr );
	if( cryptStatusError( status ) || \
		revRequestInfoPtr->attributes == NULL )
		return( status );
	return( copyRevocationAttributes( &certInfoPtr->attributes,
									  revRequestInfoPtr->attributes ) );
	}

/* Copy user certificate info into a certificate object */

static int copyUserCertInfo( CERT_INFO *certInfoPtr,
							 CERT_INFO *userCertInfoPtr,
							 const CRYPT_HANDLE iCryptHandle )
	{
	STREAM stream;
	BYTE certHash[ CRYPT_MAX_HASHSIZE ];
	int certHashLength = CRYPT_MAX_HASHSIZE, status;

	assert( userCertInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
			userCertInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );
	assert( userCertInfoPtr->certificate != NULL );

	/* If it's a CRL, copy the revocation information across */
	if( certInfoPtr->type == CRYPT_CERTTYPE_CRL )
		return( copyRevocationInfo( certInfoPtr, userCertInfoPtr ) );

	/* If it's a CRMF cert request, copy the public key and DN.  We copy the
	   full DN rather than just the encoded form in case the user wants to
	   query the request details after creating it */
	if( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT )
		{
		status = copyDN( &certInfoPtr->subjectName,
						 userCertInfoPtr->subjectName );
		if( cryptStatusError( status ) )
			return( status );
		if( certInfoPtr->iPubkeyContext != CRYPT_ERROR || \
			certInfoPtr->publicKeyInfo != NULL )
			/* If a key has already been added as
			   CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, there's nothing further
			   to do.  Checking for this (rather than returning an error)
			   allows the DN information from an existing cert to be copied
			   into a request for a new key */
			return( CRYPT_OK );
		status = copyPublicKeyInfo( certInfoPtr, iCryptHandle, NULL );
		if( cryptStatusError( status ) )
			deleteDN( &certInfoPtr->subjectName );
		return( status );
		}

	/* If it's a CRMF revocation request, copy across the issuer and serial
	   number */
	if( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION )
		{
		/* If the info is already present we can't add it again */
		if( certInfoPtr->issuerName != NULL )
			{
			setErrorInfo( certInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
						  CRYPT_ERRTYPE_ATTR_PRESENT );
			return( CRYPT_ERROR_INITED );
			}

		/* Copy across the issuer name and allocate any further storage that
		   we need.  We don't care about any internal structure of the issuer
		   DN so we just copy the pre-encoded form, we could in theory copy
		   the full DN but it isn't really the issuer (creator) of the object
		   so it's better if it appears to have no issuer DN than a
		   misleading one */
		status = copyIssuerDnData( certInfoPtr, userCertInfoPtr );
		if( cryptStatusError( status ) )
			return( status );
		status = setSerialNumber( certInfoPtr, 
								  userCertInfoPtr->cCertCert->serialNumber,
								  userCertInfoPtr->cCertCert->serialNumberLength );
		if( cryptStatusOK( status ) && \
			certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION && \
			( certInfoPtr->subjectDNdata = \
					  clAlloc( "copyUserCertInfo",
							   userCertInfoPtr->subjectDNsize ) ) == NULL )
			status = CRYPT_ERROR_MEMORY;
		if( cryptStatusError( status ) )
			{
			clFree( "copyUserCertInfo", certInfoPtr->issuerDNdata );
			certInfoPtr->issuerDNptr = certInfoPtr->issuerDNdata = NULL;
			certInfoPtr->issuerDNsize = 0;
			if( certInfoPtr->cCertCert->serialNumber != NULL && \
				certInfoPtr->cCertCert->serialNumber != \
					certInfoPtr->cCertCert->serialNumberBuffer )
				clFree( "copyUserCertInfo", 
						certInfoPtr->cCertCert->serialNumber );
			certInfoPtr->cCertCert->serialNumber = NULL;
			return( status );
			}

		/* If it's a CRMF revocation request, copy the subject DN for use in
		   CMP */
		if( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION )
			{
			memcpy( certInfoPtr->subjectDNdata, userCertInfoPtr->subjectDNptr,
					userCertInfoPtr->subjectDNsize );

⌨️ 快捷键说明

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