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

📄 certcomp.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:

		/* It's an absolute attribute position, try and move to the
		   attribute */
		if( certInfoType == CRYPT_CERTINFO_CURRENT_EXTENSION )
			{
			attributeListPtr = findAttribute( certInfoPtr->attributes, value );
			if( attributeListPtr == NULL )
				return( CRYPT_ERROR_NOTFOUND );
			certInfoPtr->attributeCursor = attributeListPtr;
			return( CRYPT_OK );
			}

		/* It's an absolute field postion, try and move to the field */
		attributeListPtr = selectNameOrField( certInfoPtr, value );
		if( attributeListPtr == NULL )
			return( CRYPT_ERROR_NOTFOUND );
		certInfoPtr->attributeCursor = attributeListPtr;
		return( CRYPT_OK );
		}

	/* We're adding data to a certificate, clear the error information */
	clearErrorInfo( certInfoPtr );

	/* If it's a public key, take a copy of the context for the certificates
	   use */
	if( certInfoType == CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO )
		return( copyPublicKey( certInfoPtr, 
							   *( ( CRYPT_HANDLE * ) certInfo ) ) );

	/* If it's a cert request, copy the public key context, the DN, any 
	   valid attributes, and any other relevant bits and pieces if it's a 
	   CRMF request */
	if( certInfoType == CRYPT_CERTINFO_CERTREQUEST )
		{
		CRYPT_CERTIFICATE certRequest = *( ( CRYPT_CERTIFICATE * ) certInfo );
		CERT_INFO *certRequestInfoPtr;

		/* Make sure we haven't already got a public key or DN present */
		if( certInfoPtr->iCryptContext != CRYPT_ERROR || \
			certInfoPtr->subjectName != NULL )
			{
			setErrorInfo( certInfoPtr, CRYPT_CERTINFO_CERTREQUEST,
						  CRYPT_ERRTYPE_ATTR_PRESENT );
			return( CRYPT_ERROR_INITED );
			}

		/* Copy the public key context, the DN, and the attributes.  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) */
		getCheckInternalResource( certRequest, certRequestInfoPtr,
								  OBJECT_TYPE_CERTIFICATE );
		if( certRequestInfoPtr->type != CRYPT_CERTTYPE_CERTREQUEST && \
			certRequestInfoPtr->type != CRYPT_CERTTYPE_REQUEST_CERT )
			unlockResourceExit( certRequestInfoPtr, CRYPT_ARGERROR_NUM1 );
		status = copyDN( &certInfoPtr->subjectName,
						 certRequestInfoPtr->subjectName );
		if( cryptStatusOK( status ) && \
			certRequestInfoPtr->attributes != NULL )
			{
			status = copyAttributes( &certInfoPtr->attributes,
									 certRequestInfoPtr->attributes,
									 &certInfoPtr->errorLocus,
									 &certInfoPtr->errorType );
			if( cryptStatusError( status ) )
				deleteDN( &certInfoPtr->subjectName );
			}
		if( cryptStatusOK( status ) )
			{
			/* The copies succeeded, add a reference from the cert to the
			   context associated with the cert request */
			certInfoPtr->iCryptContext = certRequestInfoPtr->iCryptContext;
			krnlSendMessage( certInfoPtr->objectHandle,
							 RESOURCE_IMESSAGE_SETDEPENDENT,
							 &certRequestInfoPtr->iCryptContext, 
							 SETDEP_OPTION_INCREF );
			}
		if( certRequestInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT )
			{
			/* If it's a CRMF request there could also be a validity period
			   specified */
			if( certRequestInfoPtr->startTime )
				certInfoPtr->startTime = certRequestInfoPtr->startTime;
			if( certRequestInfoPtr->endTime )
				certInfoPtr->endTime = certRequestInfoPtr->endTime;
			}
		unlockResourceExit( certRequestInfoPtr, status );
		}

	/* If it's a revocation request, copy what we need to identify the cert 
	   to be revoked and any revocation information */
	if( certInfoType == CRYPT_IATTRIBUTE_REVREQUEST )
		{
		CRYPT_CERTIFICATE certRequest = *( ( CRYPT_CERTIFICATE * ) certInfo );
		CERT_INFO *certRequestInfoPtr;

		getCheckInternalResource( certRequest, certRequestInfoPtr,
								  OBJECT_TYPE_CERTIFICATE );
		status = copyRevocationInformation( certInfoPtr, certRequestInfoPtr );
		if( cryptStatusOK( status ) )
			status = copyRevocationAttributes( &certInfoPtr->attributes,
						certRequestInfoPtr->attributes,
						&certInfoPtr->errorLocus, &certInfoPtr->errorType );
		unlockResourceExit( certRequestInfoPtr, status );
		}

	/* If it's a certificate, copy across various components or store the
	   entire cert where required */
	if( certInfoType == CRYPT_CERTINFO_USERCERTIFICATE )
		{
		CRYPT_CERTIFICATE userCert = *( ( CRYPT_HANDLE * ) certInfo );
		CERT_INFO *userCertInfoPtr;

		/* Make sure we've been passed a cert ready for use */
		status = krnlSendMessage( userCert, RESOURCE_IMESSAGE_GETDEPENDENT,
								  &userCert, OBJECT_TYPE_CERTIFICATE );
		if( cryptStatusError( status ) )
			return( status );
		getCheckInternalResource( userCert, userCertInfoPtr,
								  OBJECT_TYPE_CERTIFICATE );
		if( userCertInfoPtr->type != CRYPT_CERTTYPE_CERTIFICATE && \
			userCertInfoPtr->type != CRYPT_CERTTYPE_CERTCHAIN )
			/* Must be either a straight certificate or the cert at the end
			   of a chain (certs in the middle of the chain are extracted
			   by the higher-level code and passed down as standalone 
			   certs) */
			status = CRYPT_ARGERROR_NUM1;
		else
			if( userCertInfoPtr->certificate == NULL )
				status = CRYPT_ERROR_NOTINITED;	/* Must be ready for use */
		if( cryptStatusError( status ) )
			unlockResourceExit( userCertInfoPtr, status );

		/* If it's a cert chain we're adding the complete cert, just store it 
		   and exit */
		if( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )
			{
			int i;

			unlockResource( userCertInfoPtr );
			if( certInfoPtr->certChainEnd >= MAX_CHAINLENGTH )
				return( CRYPT_ERROR_OVERFLOW );

			/* Perform a simple check to make sure it hasn't been added
			   already */
			for( i = 0; i < certInfoPtr->certChainEnd; i++ )
				if( cryptStatusOK( \
					krnlSendMessage( userCert, RESOURCE_IMESSAGE_COMPARE, 
									 &certInfoPtr->certChain[ i ],
									 RESOURCE_MESSAGE_COMPARE_FINGERPRINT ) ) )
					{
					setErrorInfo( certInfoPtr, CRYPT_CERTINFO_USERCERTIFICATE,
								  CRYPT_ERRTYPE_ATTR_PRESENT );
					return( CRYPT_ERROR_INITED );
					}

			/* Add the user cert and increment its reference count */
			krnlSendNotifier( userCert, RESOURCE_IMESSAGE_INCREFCOUNT );
			certInfoPtr->certChain[ certInfoPtr->certChainEnd++ ] = userCert;
			return( CRYPT_OK );
			}

		/* 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 ) )
				unlockResourceExit( userCertInfoPtr, status );
			status = copyPublicKey( certInfoPtr, 
									*( ( CRYPT_HANDLE * ) certInfo ) );
			if( cryptStatusError( status ) )
				deleteDN( &certInfoPtr->subjectName );
			unlockResourceExit( userCertInfoPtr, 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_USERCERTIFICATE,
							  CRYPT_ERRTYPE_ATTR_PRESENT );
				unlockResourceExit( userCertInfoPtr, CRYPT_ERROR_INITED );
				}

			/* Copy across the issuer name and serial number.  We don't care
			   about any internal structure 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 = copyIssuerDN( certInfoPtr, userCertInfoPtr );
			if( cryptStatusError( status ) )
				unlockResourceExit( userCertInfoPtr, status );
			if( ( certInfoPtr->serialNumber = \
				  malloc( userCertInfoPtr->serialNumberLength ) ) == NULL )
				unlockResourceExit( userCertInfoPtr, CRYPT_ERROR_MEMORY );
			memcpy( certInfoPtr->serialNumber, userCertInfoPtr->serialNumber,
					userCertInfoPtr->serialNumberLength );
			certInfoPtr->serialNumberLength = userCertInfoPtr->serialNumberLength;

			/* If it's a CRMF revocation request we also need to copy the 
			   subject DN for use in CMP */
			if( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION )
				{
				if( ( certInfoPtr->subjectDNdata = \
					  malloc( userCertInfoPtr->subjectDNsize ) ) == NULL )
					{
					free( certInfoPtr->serialNumber );
					certInfoPtr->serialNumber = NULL;
					free( certInfoPtr->issuerDNdata );
					certInfoPtr->issuerDNdata = NULL;
					unlockResourceExit( userCertInfoPtr, CRYPT_ERROR_MEMORY );
					}
				memcpy( certInfoPtr->subjectDNdata, userCertInfoPtr->subjectDNptr,
						userCertInfoPtr->subjectDNsize );
				certInfoPtr->subjectDNptr = certInfoPtr->subjectDNdata;
				certInfoPtr->subjectDNsize = userCertInfoPtr->subjectDNsize;
				}

			unlockResourceExit( userCertInfoPtr, status );
			}

		/* If it's an OCSP request, remember the OCSP responder URL if 
		   there's one present (we can't leave it to be read out of the cert 
		   because authorityInfoAccess isn't a valid attribute for OCSP 
		   requests) and copy the cert information to the revocation list */
		if( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST )
			{
			int sizeofOCSPv1ID( const CERT_INFO *certInfoPtr );
			int writeOCSPv1ID( STREAM *stream, const CERT_INFO *certInfoPtr, 
							   const void *issuerKeyHash );
			ATTRIBUTE_LIST *attributeListPtr = NULL;
			SELECTION_STATE savedState;
			STREAM stream;
			BYTE certHash[ CRYPT_MAX_HASHSIZE ];
			int certHashLength = CRYPT_MAX_HASHSIZE;

			/* Check whether the user cert conatains an OCSP responder URL 
			   in the OCSP authorityInfoAccess GeneralName. Since this 
			   changes the GeneralName selection state within the cert we 
			   save it around the selection calls */
			saveSelectionState( savedState, userCertInfoPtr );
			if( selectGeneralName( userCertInfoPtr,
						CRYPT_CERTINFO_AUTHORITYINFO_OCSP, SELECT_SELECT ) != NULL )
				attributeListPtr = selectGeneralName( userCertInfoPtr,
								CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, 
								SELECT_SET );
			restoreSelectionState( savedState, userCertInfoPtr );
			if( attributeListPtr != NULL && certInfoPtr->ocspUrl == NULL )
				{
				/* There's an OCSP responder URL present, copy it to the OCSP 
				   request */
				if( ( certInfoPtr->ocspUrl = \
							malloc( attributeListPtr->dataLength ) ) == NULL )
						unlockResourceExit( userCertInfoPtr, 
											CRYPT_ERROR_MEMORY );
				memcpy( certInfoPtr->ocspUrl, 
						( attributeListPtr->data != NULL ) ? \
							attributeListPtr->data : attributeListPtr->smallData,
						attributeListPtr->dataLength );
				certInfoPtr->ocspUrlSize = attributeListPtr->dataLength;
				}

			/* If the caller wants an OCSPv1 ID, we add the necessary 
			   information as a pre-encoded blob since we can't do much with
			   the ID fields */
			if( certInfoPtr->version == 1 )
				{
				BYTE idBuffer[ 256 ], *idBufPtr = idBuffer;
				int idLength;

				idLength = sizeofOCSPv1ID( userCertInfoPtr );
				if( idLength > 256 && \
				    ( idBufPtr = malloc( idLength ) ) == NULL )
					unlockResourceExit( userCertInfoPtr, 
										CRYPT_ERROR_MEMORY );
				sMemOpen( &stream, idBufPtr, idLength );
				status = writeOCSPv1ID( &stream, userCertInfoPtr,
										certInfoPtr->certHash );
				sMemDisconnect( &stream );
				if( cryptStatusOK( status ) )
					status = addRevocationEntry( &certInfoPtr->revocations,
												 &certInfoPtr->currentRevocation, 
												 CRYPT_ATTRIBUTE_NONE, 
												 idBufPtr, idLength );
				if( idBufPtr != idBuffer )
					free( idBufPtr );
				}
			else
				{
				/* It's not an OCSPv1 request, make the version explicit */
				certInfoPtr->version = 2;

				/* It's a v2 request, add the cert hash.  We read the cert 
				   hash indirectly since it's computed on demand and may not 
				   have been evaluated yet */
				status = getCertComponent( userCertInfoPtr,
										   CRYPT_CERTINFO_FINGERPRINT_SHA,
										   certHash, &certHashLength );
				if( cryptStatusOK( status ) )
					status = addRevocationEntry( &certInfoPtr->revocations,
												 &certInfoPtr->currentRevocation, 
												 CRYPT_CERTINFO_FINGERPRINT, 
												 certHash, certHashLength );
				}
			if( status == CRYPT_ERROR_DUPLICATE )
				/* If this cert is already present in the list, set the 
				   extended error code for it */
				setErrorInfo( certInfoPtr, CRYPT_CERTINFO_USERCERTIFICATE,
							  CRYPT_ERRTYPE_ATTR_PRESENT );
			unlockResourceExit( userCertInfoPtr, status );
			}

		/* It's a CRL, copy the revocation information across */
		assert( certInfoPtr->type == CRYPT_CERTTYPE_CRL );
		status = copyRevocationInformation( certInfoPtr, userCertInfoPtr );
		unlockResourceExit( userCertInfoPtr, status );
		}

	/* If it's a CA certificate, get the hash of the public key (for an OCSP 
	   request), possibly overwriting a previous hash if there are multiple
	   entries in the request */
	if( certInfoType == CRYPT_CERTINFO_CACERTIFICATE )
		{
		CRYPT_CERTIFICATE caCert = *( ( CRYPT_HANDLE * ) certInfo );
		CERT_INFO *caCertInfoPtr;
		HASHFUNCTION hashFunction;
		STREAM stream;
		int length, hashSize;

		getHashParameters( CRYPT_ALGO_SHA, &hashFunction, &hashSize );

		/* If we've already added revocation entries with v2 IDs we can't add
		   a CA cert which implies v1 IDs */
		if( certInfoPtr->version == 2 )
			{
			setErrorInfo( certInfoPtr, CRYPT_CERTINFO_USERCERTIFICATE,
						  CRYPT_ERRTYPE_ATTR_PRESENT );
			return( CRYPT_ERROR_INITED );
			}

		/* Make sure we've been passed a cert ready for use */
		status = krnlSendMessage( caCert, RESOURCE_IMESSAGE_GETDEPENDENT,
								  &caCert, OBJECT_TYPE_CERTIFICATE );
		if( cryptStatusError( status ) )
			return( status );
		getCheckInternalResource( caCert, caCertInfoPtr,
								  OBJECT_TYPE_CERTIFICATE );

⌨️ 快捷键说明

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