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

📄 certcget.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:
	if( cryptStatusOK( \
			moveCursorToField( certInfoPtr,
							   certInfoPtr->currentSelection.generalName ) ) )
		return( CRYPT_OK );
	if( option == MUST_BE_PRESENT )
		return( CRYPT_ERROR_NOTFOUND );

	/* We're creating the GeneralName extension, deselect the current DN and
	   remember that we have to update the extension cursor when we've done
	   it */
	certInfoPtr->currentSelection.dnPtr = NULL;
	certInfoPtr->currentSelection.dnInExtension = FALSE;
	certInfoPtr->currentSelection.updateCursor = TRUE;
	assert( selectionInfoConsistent( certInfoPtr ) );
	return( CRYPT_OK );
	}

/* Handle selection of DNs */

int selectDN( CERT_INFO *certInfoPtr, const CRYPT_ATTRIBUTE_TYPE certInfoType,
			  const SELECTION_OPTION option )
	{
	CRYPT_ATTRIBUTE_TYPE generalName = \
							certInfoPtr->currentSelection.generalName;
	static const int value = CRYPT_UNUSED;
	int status;

	assert( ( option == MAY_BE_ABSENT && \
			  isDNSelectionComponent( certInfoType ) ) || \
			( ( option == MUST_BE_PRESENT || option == CREATE_IF_ABSENT ) && \
			  certInfoType == CRYPT_ATTRIBUTE_NONE ) );
	assert( selectionInfoConsistent( certInfoPtr ) );

	if( option == MAY_BE_ABSENT )
		{
		/* Try and select a DN based on the supplied attribute ID */
		switch( certInfoType )
			{
			case CRYPT_CERTINFO_SUBJECTNAME:
				certInfoPtr->currentSelection.dnPtr = &certInfoPtr->subjectName;
				break;

			case CRYPT_CERTINFO_ISSUERNAME:
				certInfoPtr->currentSelection.dnPtr = &certInfoPtr->issuerName;

				/* If it's a self-signed cert and the issuer name isn't
				   explicitly present then it must be implicitly present as
				   the subject name */
				if( certInfoPtr->issuerName == NULL && \
					( certInfoPtr->flags & CERT_FLAG_SELFSIGNED ) )
					certInfoPtr->currentSelection.dnPtr = &certInfoPtr->subjectName;
				break;

			default:
				assert( NOTREACHED );
				return( CRYPT_ARGERROR_VALUE );
			}

		/* We've selected a built-in DN, remember that this isn't one in an
		   (optional) extension */
		certInfoPtr->currentSelection.dnInExtension = FALSE;
		assert( selectionInfoConsistent( certInfoPtr ) );
		return( CRYPT_OK );
		}

	/* If there's a DN already selected, we're done */
	if( certInfoPtr->currentSelection.dnPtr != NULL )
		return( CRYPT_OK );

	assert( option == MUST_BE_PRESENT || option == CREATE_IF_ABSENT );

	/* To select a DN in a GeneralName, we first need to have a GeneralName
	   selected */
	status = selectGeneralName( certInfoPtr, CRYPT_ATTRIBUTE_NONE, option );
	if( cryptStatusError( status ) )
		return( status );

	/* If we've now got a GeneralName selected, try and find a DN in it */
	if( isGeneralNameSelected( certInfoPtr ) )
		{
		/* If there's a DN currently selected, we're done */
		if( certInfoPtr->attributeCursor->fieldType == FIELDTYPE_DN )
			{
			certInfoPtr->currentSelection.dnPtr = \
							&certInfoPtr->attributeCursor->value;
			certInfoPtr->currentSelection.dnInExtension = TRUE;
			assert( selectionInfoConsistent( certInfoPtr ) );
			return( CRYPT_OK );
			}

		/* There's no DN selected, see if there's one present somewhere in
		   the extension */
		if( cryptStatusOK( findDnInExtension( certInfoPtr, TRUE ) ) )
			return( CRYPT_OK );

		/* If there's no DN present and we're not about to create one,
		   exit */
		if( option == MUST_BE_PRESENT )
			return( CRYPT_ERROR_NOTFOUND );

		/* Create the DN in the currently selected GeneralName */
		generalName = certInfoPtr->attributeCursor->fieldID;
		}

	/* We're being asked to instantiate the DN, create the attribute field
	   that contains it */
	status = addAttributeField( &certInfoPtr->attributes, generalName,
						CRYPT_CERTINFO_DIRECTORYNAME, &value, CRYPT_UNUSED,
						ATTR_FLAG_NONE, &certInfoPtr->errorLocus,
						&certInfoPtr->errorType );
	if( cryptStatusError( status ) )
		return( status );

	/* Find the field that we just created.  This is a newly-created
	   attribute, so it's the only one present (i.e we don't have to worry
	   about finding one added at the end of the sequence of identical
	   attributes), and we also know that it must be present since we've
	   just created it */
	return( selectGeneralName( certInfoPtr, generalName, MAY_BE_ABSENT ) );
	}

/****************************************************************************
*																			*
*									Get Cert Info							*
*																			*
****************************************************************************/

/* Get a certificate component */

static int getCertAttributeComponentData( const ATTRIBUTE_LIST *attributeListPtr,
										  void *certInfo, int *certInfoLength )
	{
	const int maxLength = ( certInfoLength != NULL ) ? *certInfoLength : 0;

	/* If the data type is an OID, we have to convert it to a human-readable
	   form before we return it */
	if( attributeListPtr->fieldType == BER_OBJECT_IDENTIFIER )
		{
		char textOID[ CRYPT_MAX_TEXTSIZE * 2 ];
		int length;

		assert( certInfoLength != NULL );

		length = oidToText( attributeListPtr->value, textOID );
		*certInfoLength = length;
		if( certInfo == NULL )
			return( CRYPT_OK );
		if( length > maxLength )
			return( CRYPT_ERROR_OVERFLOW );
		memcpy( certInfo, textOID, length );
		return( CRYPT_OK );
		}

	/* If it's a basic data value, copy it over as an integer */
	if( attributeListPtr->valueLength <= 0 )
		{
		*( ( int * ) certInfo ) = ( int ) attributeListPtr->intValue;
		return( CRYPT_OK );
		}
	assert( certInfoLength != NULL );

	/* It's a more complex data type, copy it across */
	*certInfoLength = attributeListPtr->valueLength;
	if( certInfo == NULL )
		return( CRYPT_OK );
	if( attributeListPtr->valueLength > maxLength )
		return( CRYPT_ERROR_OVERFLOW );
	memcpy( certInfo, attributeListPtr->value, attributeListPtr->valueLength );
	return( CRYPT_OK );
	}

static int getCertAttributeComponent( CERT_INFO *certInfoPtr,
									  const CRYPT_ATTRIBUTE_TYPE certInfoType,
									  void *certInfo, int *certInfoLength )
	{
	ATTRIBUTE_LIST *attributeListPtr;

	assert( ( certInfo == NULL && *certInfoLength == 0 ) || \
			( certInfoLength == NULL ) || \
			( *certInfoLength > 1 && *certInfoLength <= 32768 ) );

	/* Try and find this attribute in the attribute list */
	if( isRevocationEntryComponent( certInfoType ) )
		{
		/* If it's an RTCS per-entry attribute, get the attribute from the
		   currently selected entry */
		if( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST || \
			certInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE )
			{
			if( certInfoPtr->currentValidity == NULL )
				return( CRYPT_ERROR_NOTFOUND );
			attributeListPtr = findAttributeFieldEx( \
					certInfoPtr->currentValidity->attributes, certInfoType );
			}
		else
			{
			/* It's a CRL or OCSP per-entry attribute, get the attribute 
			   from the currently selected entry */
			if( certInfoPtr->currentRevocation == NULL )
				return( CRYPT_ERROR_NOTFOUND );
			attributeListPtr = findAttributeFieldEx( \
				certInfoPtr->currentRevocation->attributes, certInfoType );
			if( attributeListPtr == NULL && \
				certInfoType == CRYPT_CERTINFO_CRLREASON )
				/* Revocation reason codes are actually a single range of 
				   values spread across two different extensions, so if we 
				   don't find the value as a straight cRLReason we try 
				   again for a cRLExtReason.  If we've been specifically 
				   asked for a cRLExtReason we don't go the other way 
				   because the caller (presumably) specifically wants the 
				   extended reason code */
				attributeListPtr = findAttributeFieldEx( \
								certInfoPtr->currentRevocation->attributes,
								CRYPT_CERTINFO_CRLEXTREASON );
			}
		}
	else
		attributeListPtr = findAttributeFieldEx( certInfoPtr->attributes,
												 certInfoType );
	if( attributeListPtr == NULL )
		return( CRYPT_ERROR_NOTFOUND );

	/* If this is a non-present field in a present attribute with a default
	   value for the field, return that */
	if( isDefaultFieldValue( attributeListPtr ) )
		{
		*( ( int * ) certInfo ) = getDefaultFieldValue( certInfoType );
		return( CRYPT_OK );
		}

	/* If this is a non-present field in a present attribute which denotes
	   an entire (constructed) attribute, return a boolean indicating its
	   presence */
	if( isCompleteAttribute( attributeListPtr ) )
		{
		*( ( int * ) certInfo ) = TRUE;
		return( CRYPT_OK );
		}

	return( getCertAttributeComponentData( attributeListPtr, certInfo,
										   certInfoLength ) );
	}

/* Get the hash of a certificate */

static int getCertHash( CERT_INFO *certInfoPtr,
						const CRYPT_ATTRIBUTE_TYPE certInfoType, 
						void *certInfo, int *certInfoLength )
	{
	const CRYPT_ALGO_TYPE cryptAlgo = \
				( certInfoType == CRYPT_CERTINFO_FINGERPRINT_MD5 ) ? \
				CRYPT_ALGO_MD5 : CRYPT_ALGO_SHA;
	HASHFUNCTION hashFunction;
	BYTE hash[ CRYPT_MAX_HASHSIZE ];
	const int maxLength = *certInfoLength;
	int hashSize;

	/* Get the hash algorithm information */
	getHashParameters( cryptAlgo, &hashFunction, &hashSize );
	*certInfoLength = hashSize;
	if( certInfo == NULL )
		return( CRYPT_OK );
	if( hashSize > maxLength )
		return( CRYPT_ERROR_OVERFLOW );
	assert( certInfoPtr->certificate != NULL );

	/* Write the hash (fingerprint) to the output */
	if( cryptAlgo == CRYPT_ALGO_SHA && certInfoPtr->certHashSet )
		{
		/* If we've got a cached hash present, return that instead of re-
		   hashing the cert */
		memcpy( certInfo, certInfoPtr->certHash, KEYID_SIZE );
		return( CRYPT_OK );
		}
	hashFunction( NULL, hash, certInfoPtr->certificate,
				  certInfoPtr->certificateSize, HASH_ALL );
	memcpy( certInfo, hash, hashSize );
	if( cryptAlgo == CRYPT_ALGO_SHA )
		{
		/* Remember the hash/fingerprint/oobCertID/certHash/thumbprint/
		   whatever for later, since this is reused frequently */
		memcpy( certInfoPtr->certHash, hash, hashSize );
		certInfoPtr->certHashSet = TRUE;
		}
	return( CRYPT_OK );
	}

/* Get a single CRL entry */

static int getCrlEntry( CERT_INFO *certInfoPtr, void *certInfo, 
						int *certInfoLength )
	{
	STREAM stream;
	const int maxLength = *certInfoLength;
	int crlEntrySize, i, status;

	assert( certInfoPtr->type == CRYPT_CERTTYPE_CRL );

	if( certInfoPtr->currentRevocation == NULL )
		return( CRYPT_ERROR_NOTFOUND );

	/* Determine how big the encoded CRL entry will be.  This is somewhat 
	   ugly since we have to pick the necessary function out of the cert 
	   write-function table, but the only other way to do it would be to 
	   pseudo-sign the cert object in order to write the data, which 
	   doesn't work for CRL entries where we could end up pseudo-singing it 
	   multiple times */
	for( i = 0; certWriteTable[ i ].type != CRYPT_CERTTYPE_CRL && \
				certWriteTable[ i ].type != CRYPT_CERTTYPE_NONE; i++ );
	if( certWriteTable[ i ].type == CRYPT_CERTTYPE_NONE )
		{
		assert( NOTREACHED );
		return( CRYPT_ERROR_NOTAVAIL );
		}
	sMemOpen( &stream, NULL, 0 );
	status = certWriteTable[ i ].writeFunction( &stream, certInfoPtr,
												NULL, CRYPT_UNUSED );
	crlEntrySize = stell( &stream );
	sMemClose( &stream );
	if( cryptStatusError( status ) )
		return( status );

	/* Write the encoded single CRL entry */
	*certInfoLength = crlEntrySize;
	if( certInfo == NULL )
		return( CRYPT_OK );
	if( crlEntrySize > maxLength )
		return( CRYPT_ERROR_OVERFLOW );
	sMemOpen( &stream, certInfo, crlEntrySize );
	status = certWriteTable[ i ].writeFunction( &stream, certInfoPtr,
												NULL, CRYPT_UNUSED );
	sMemDisconnect( &stream );

	return( status );
	}

/* Get the issuerAndSerialNumber for a certificate */

static int getIAndS( CERT_INFO *certInfoPtr, void *certInfo, 
					 int *certInfoLength )
	{
	STREAM stream;
	void *serialNumber;
	const int maxLength = *certInfoLength;
	int serialNumberLength, status;

	if( certInfoPtr->type == CRYPT_CERTTYPE_CRL )
		{
		REVOCATION_INFO *crlInfoPtr = certInfoPtr->currentRevocation;

		/* If it's a CRL, use the serial number of the currently selected 
		   CRL entry */
		assert( crlInfoPtr != NULL );

		serialNumber = crlInfoPtr->dataPtr;
		serialNumberLength = crlInfoPtr->dataLength;
		}
	else
		{
		serialNumber = certInfoPtr->serialNumber;
		serialNumberLength = certInfoPtr->serialNumberLength;
		}
	assert( serialNumber != NULL );
	*certInfoLength = ( int ) \
		sizeofObject( certInfoPtr->issuerDNsize + \
					  sizeofInteger( serialNumber, serialNumberLength ) );
	if( certInfo == NULL )
		return( CRYPT_OK );
	if( *certInfoLength > maxLength )
		return( CRYPT_ERROR_OVERFLOW );
	sMemOpen( &stream, certInfo, *certInfoLength );
	writeSequence( &stream, certInfoPtr->issuerDNsize + \
				   sizeofInteger( serialNumber, serialNumberLength ) );
	swrite( &stream, certInfoPtr->issuerDNptr, certInfoPtr->issuerDNsize );
	status = writeInteger( &stream, serialNumber, serialNumberLength,
						   DEFAULT_TAG );
	sMemDisconnect( &stream );

	return( status );
	}

/* Get the ESSCertID for a certificate */

static int getESSCertID( CERT_INFO *certInfoPtr, void *certInfo, 
						 int *certInfoLength )
	{
	STREAM stream;

⌨️ 快捷键说明

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