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

📄 certstr.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:
				( DN_COMPONENT * ) malloc( sizeof( DN_COMPONENT ) ) ) == NULL ) || \
			( srcPtr->value != srcPtr->smallValue && \
			  ( valuePtr = malloc( srcPtr->valueLength ) ) == NULL ) )
			{
			if( newElement != NULL )
				free( newElement );
			deleteDN( dnDest );
			return( CRYPT_ERROR_MEMORY );
			}
		memcpy( newElement, srcPtr, sizeof( DN_COMPONENT ) );
		if( srcPtr->value == srcPtr->smallValue )
			newElement->value = newElement->smallValue;
		else
			{
			memcpy( valuePtr, srcPtr->value, srcPtr->valueLength );
			newElement->value = valuePtr;
			}

		/* Link it into the list */
		if( destPtr == NULL )
			{
			*dnDest = destPtr = newElement;
			newElement->prev = newElement->next = NULL;
			}
		else
			{
			newElement->prev = destPtr;
			newElement->next = NULL;
			destPtr->next = newElement;
			destPtr = newElement;
			}
		}

	return( CRYPT_OK );
	}

/* Check the validity of a DN.  The check for the bottom of the DN (common
   name) and top (country) are made configurable, DN's which act as filters
   (eg path constraints) may not have the lower DN parts present, and cert
   requests submitted to CA's which set the country themselves may not have
   the country present */

int checkDN( const void *dnComponentListHead,
			 const BOOLEAN checkCN, const BOOLEAN checkC,
			 CRYPT_ATTRIBUTE_TYPE *errorLocus,
			 CRYPT_ERRTYPE_TYPE *errorType )
	{
	DN_COMPONENT *dnComponentListPtr;
	BOOLEAN hasCountry = TRUE, hasCommonName = FALSE;

	/* Clear the return values */
	*errorType = CRYPT_OK;
	*errorLocus = CRYPT_ATTRIBUTE_NONE;

	/* Make sure that certain critical components are present */
	for( dnComponentListPtr = ( DN_COMPONENT * ) dnComponentListHead;
		 dnComponentListPtr != NULL;
		 dnComponentListPtr = dnComponentListPtr->next )
		{
		if( dnComponentListPtr->type == CRYPT_CERTINFO_COUNTRYNAME )
			{
			if( !checkCountryCode( ( char * ) dnComponentListPtr->value ) )
				{
				*errorType = CRYPT_ERRTYPE_ATTR_VALUE;
				*errorLocus = CRYPT_CERTINFO_COUNTRYNAME;
				return( CRYPT_ERROR_INVALID );
				}
			hasCountry = TRUE;
			}
		if( dnComponentListPtr->type == CRYPT_CERTINFO_COMMONNAME )
			hasCommonName = TRUE;
		}
	if( ( checkC && !hasCountry ) || ( checkCN && !hasCommonName ) )
		{
		*errorType = CRYPT_ERRTYPE_ATTR_ABSENT;
		*errorLocus = ( hasCountry ) ? CRYPT_CERTINFO_COMMONNAME : \
									   CRYPT_CERTINFO_COUNTRYNAME;
		return( CRYPT_ERROR_NOTINITED );
		}

	return( CRYPT_OK );
	}

/* Convert a DN component containing a PKCS #9 emailAddress or an (????)
   rfc822Mailbox into an rfc822Name */

static int convertEmail( CERT_INFO *certInfoPtr, void **dnListHead,
						 const CRYPT_ATTRIBUTE_TYPE altNameType )
	{
	DN_COMPONENT *emailComponent = findDNComponentByOID( *dnListHead,
			( const BYTE * ) "\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01" );
	SELECTION_STATE selectionState;
	const int dummy = CRYPT_UNUSED;
	int status;

	/* If there's no PKCS #9 email address present, try for a (????) one.  If
	   that's not present either, exit */
	if( emailComponent == NULL )
		{
		emailComponent = findDNComponentByOID( *dnListHead,
			( const BYTE * ) "\x06\x09\x09\x92\x26\x89\x93\xF2\x2C\x01\x03" );
		if( emailComponent == NULL )
			return( CRYPT_OK );
		}

	/* Try and add the email address component as an rfc822Name.  Since this
	   changes the current GeneralName selection, we have to be careful about
	   saving and restoring the state */
	saveSelectionState( selectionState, certInfoPtr );
	addCertComponent( certInfoPtr, altNameType, &dummy, 0 );
	status = addCertComponent( certInfoPtr, CRYPT_CERTINFO_RFC822NAME,
							   emailComponent->value,
							   emailComponent->valueLength );
	if( status == CRYPT_ERROR_INITED )
		/* If it's already present (which is somewhat odd since the presence
		   of an email address in the DN implies that the implementation
		   doesn't know about rfc822Name) we can't do anything about it */
		status = CRYPT_OK;
	else
		/* It was successfully copied over, delete the copy in the DN */
		deleteComponent( dnListHead, emailComponent );
	restoreSelectionState( selectionState, certInfoPtr );

	return( status );
	}

int convertEmailAddress( CERT_INFO *certInfoPtr )
	{
	int status;

	status = convertEmail( certInfoPtr, &certInfoPtr->subjectName,
						   CRYPT_CERTINFO_SUBJECTALTNAME );
	if( cryptStatusOK( status ) )
		status = convertEmail( certInfoPtr, &certInfoPtr->issuerName,
							   CRYPT_CERTINFO_ISSUERALTNAME );
	return( status );
	}

/* Perform the pre-encoding processing for a DN */

static int preEncodeDN( const DN_COMPONENT *dnComponentListHead )
	{
	DN_COMPONENT *dnComponentPtr = ( DN_COMPONENT * ) dnComponentListHead;
	int size = 0;

	assert( dnComponentPtr != NULL );

	/* If we're being fed an entry in the middle of a DN, move back to the
	   start */
	if( dnComponentPtr != NULL )
		while( dnComponentPtr->prev != NULL )
			dnComponentPtr = dnComponentPtr->prev;

	/* Walk down the DN pre-encoding each AVA */
	while( dnComponentPtr != NULL )
		{
		DN_COMPONENT *rdnStartPtr = dnComponentPtr;
		BOOLEAN isContinued;

		/* Calculate the size of every AVA in this RDN */
		do
			{
			const DN_COMPONENT_INFO *dnComponentInfo = dnComponentPtr->typeInfo;

			dnComponentPtr->encodedAVAdataSize = \
						sizeofOID( dnComponentInfo->oid ) + \
						( int ) sizeofObject( dnComponentPtr->valueLength );
			dnComponentPtr->encodedRDNdataSize = 0;
			rdnStartPtr->encodedRDNdataSize += ( int ) \
						sizeofObject( dnComponentPtr->encodedAVAdataSize );
			isContinued = dnComponentPtr->flags & DN_FLAG_CONTINUED;
			dnComponentPtr = dnComponentPtr->next;
			}
		while( isContinued && dnComponentPtr != NULL );

		/* Calculate the overall size of the RDN */
		size += ( int ) sizeofObject( rdnStartPtr->encodedRDNdataSize );
		}

	return( size );
	}

int sizeofDN( const void *dnComponentListHead )
	{
	return( sizeofObject( preEncodeDN( dnComponentListHead ) ) );
	}

/* Write a DN */

int writeDN( STREAM *stream, const void *dnComponentListHead,
			 const int tag )
	{
	DN_COMPONENT *dnComponentPtr;
	const int size = preEncodeDN( dnComponentListHead );

	/* Write the DN */
	if( tag == DEFAULT_TAG )
		writeSequence( stream, size );
	else
		writeConstructed( stream, size, tag );

	for( dnComponentPtr = ( DN_COMPONENT * ) dnComponentListHead;
		 dnComponentPtr != NULL; dnComponentPtr = dnComponentPtr->next )
		{
		const DN_COMPONENT_INFO *dnComponentInfo = dnComponentPtr->typeInfo;
		int tag;

		if( dnComponentPtr->encodedRDNdataSize )
			/* If it's the start of an RDN, write the RDN header */
			writeSet( stream, dnComponentPtr->encodedRDNdataSize );
		writeSequence( stream, dnComponentPtr->encodedAVAdataSize );
		swrite( stream, dnComponentInfo->oid, \
				sizeofOID( dnComponentInfo->oid ) );
		switch( dnComponentPtr->stringType )
			{
			case STRINGTYPE_UNICODE:
				tag = BER_STRING_BMP;
				break;

			case STRINGTYPE_PRINTABLE:
				tag = BER_STRING_PRINTABLE;
				break;

			case STRINGTYPE_IA5:
				tag = dnComponentInfo->IA5OK ? BER_STRING_IA5 : BER_STRING_T61;
				break;

			case STRINGTYPE_T61:
				tag = BER_STRING_T61;
				break;

			default:
				assert( NOTREACHED );
			}
		writeCharacterString( stream, dnComponentPtr->value,
							  dnComponentPtr->valueLength, tag );
		}

	return( sGetStatus( stream ) );
	}

/* Write a DN in string form */

int writeDNstring( STREAM *stream, const void *dnComponentListHead )
	{
	const DN_COMPONENT *dnComponentPtr = dnComponentListHead;

	if( dnComponentPtr == NULL )
		return( CRYPT_OK );

	/* Find the end of the DN string.  We have to print the RDNs backwards
	   because of ISODE's Janet memorial backwards encoding */
	while( dnComponentPtr->next != NULL )
		dnComponentPtr = dnComponentPtr->next;

	do
		{
		const DN_COMPONENT *dnComponentCursor;
		BOOLEAN isContinued;

		/* Find the start of the RDN */
		while( dnComponentPtr->prev != NULL && \
			   ( dnComponentPtr->prev->flags & DN_FLAG_CONTINUED ) )
			dnComponentPtr = dnComponentPtr->prev;
		dnComponentCursor = dnComponentPtr;
		dnComponentPtr = dnComponentPtr->prev;

		/* Print the current RDN */
		do
			{
			const DN_COMPONENT_INFO *componentInfoPtr = \
										dnComponentCursor->typeInfo;
			int i;

			/* Print the current AVA */
			swrite( stream, componentInfoPtr->name,
					strlen( componentInfoPtr->name ) );
			sputc( stream, '=' );
			for( i = 0; i < dnComponentCursor->valueLength; i++ )
				{
				const char ch = ( ( char * ) dnComponentCursor->value )[ i ];

				if( ch == ',' || ch == '=' || ch == '+' || ch == ';' || \
					ch == '\\' || ch == '"' )
					sputc( stream, '\\' );
				sputc( stream, ch );
				}

			/* If there are more AVAs in this RDN, print a continuation
			   indicator and move on to the next AVA */
			isContinued = dnComponentCursor->flags & DN_FLAG_CONTINUED;
			if( isContinued )
				{
				swrite( stream, " + ", 3 );
				dnComponentCursor = dnComponentCursor->next;
				}
			}
		while( isContinued );

		/* If there are more components to come, print an RDN separator */
		if( dnComponentPtr != NULL )
			swrite( stream, ", ", 2 );
		}
	while( dnComponentPtr != NULL );

	return( sGetStatus( stream ) );
	}

/* Parse an AVA.   This determines the AVA type and leaves the stream pointer
   at the start of the data value */

static int readAVA( STREAM *stream, CRYPT_ATTRIBUTE_TYPE *type, int *length,
					ASN1_STRINGTYPE *stringType )
	{
	BYTE oid[ MAX_OID_SIZE ];
	int oidLength, tag, i, status;

	/* Clear return values */
	*type = CRYPT_ATTRIBUTE_NONE;
	*length = 0;
	*stringType = STRINGTYPE_NONE;

	/* Read the start of the AVA and determine the type from the AttributeType
	   field.  If we find something which cryptlib doesn't recognise, we
	   indicate it as a non-component type which can be read or written but
	   not directly accessed by the user (although it can be accessed using
	   the cursor functions) */
	readSequence( stream, NULL );
	status = readRawObject( stream, oid, &oidLength, MAX_OID_SIZE,
							BER_OBJECT_IDENTIFIER );
	if( cryptStatusError( status ) )
		return( status );
	for( i = 0; certInfoOIDs[ i ].oid != NULL; i++ )
		if( !memcmp( certInfoOIDs[ i ].oid, oid, oidLength ) )
			{
			*type = ( certInfoOIDs[ i ].type != CRYPT_ATTRIBUTE_NONE ) ?
					certInfoOIDs[ i ].type : i + DN_OID_OFFSET;
			break;
			}
	if( *type == CRYPT_ATTRIBUTE_NONE )
		{
		/* If we don't recognise the component type, skip it */
		readUniversal( stream );
		return( OK_SPECIAL );
		}

	/* We've reached the data value, make sure it's in order */
	tag = readTag( stream );
	if( tag == BER_BITSTRING )
		{
		/* Bitstrings are used for uniqueIdentifiers, however these usually
		   encapsulate something else so we dig one level deeper to find the
		   encapsulated string */
		readShortLength( stream );
		sgetc( stream );	/* Skip bit count */
		tag = readTag( stream );
		}
	switch( tag )
		{
		case BER_STRING

⌨️ 快捷键说明

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