certext.c
来自「提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发」· C语言 代码 · 共 1,330 行 · 第 1/4 页
C
1,330 行
/****************************************************************************
* *
* Certificate Attribute Management Routines *
* Copyright Peter Gutmann 1996-2002 *
* *
****************************************************************************/
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#if defined( INC_ALL ) || defined( INC_CHILD )
#include "asn1.h"
#include "cert.h"
#include "certattr.h"
#else
#include "keymgmt/asn1.h"
#include "keymgmt/cert.h"
#include "keymgmt/certattr.h"
#endif /* Compiler-specific includes */
/* Prototypes for functions in cryptcrt.c */
int textToOID( const char *oid, const int oidLength, BYTE *binaryOID );
/****************************************************************************
* *
* Attribute Type Mapping *
* *
****************************************************************************/
/* Get the attribute information for a given OID */
const ATTRIBUTE_INFO *oidToAttribute( const ATTRIBUTE_TYPE attributeType,
const BYTE *oid )
{
const ATTRIBUTE_INFO *attributeInfoPtr = \
selectAttributeInfo( attributeType );
const int length = sizeofOID( oid );
while( attributeInfoPtr->fieldID != CRYPT_ERROR )
{
if( attributeInfoPtr->oid != NULL && \
sizeofOID( attributeInfoPtr->oid ) == length && \
!memcmp( attributeInfoPtr->oid, oid, length ) )
return( attributeInfoPtr );
attributeInfoPtr++;
}
/* It's an unknown attribute */
return( NULL );
}
/* Get the attribute and attributeID for a field ID */
static const ATTRIBUTE_INFO *fieldIDToAttribute( const ATTRIBUTE_TYPE attributeType,
const CRYPT_ATTRIBUTE_TYPE fieldID, const CRYPT_ATTRIBUTE_TYPE subFieldID,
CRYPT_ATTRIBUTE_TYPE *attributeID )
{
const ATTRIBUTE_INFO *attributeInfoPtr = \
selectAttributeInfo( attributeType );
int i;
/* Clear the return value */
if( attributeID != NULL )
*attributeID = CRYPT_ERROR;
/* Find the information on this attribute field */
for( i = 0; attributeInfoPtr[ i ].fieldID != CRYPT_ERROR; i++ )
{
/* If the previous entry doesn't have more data following it, the
current entry is the start of a complete attribute and therefore
contains the attribute ID */
if( attributeID != NULL && \
( !i || !( attributeInfoPtr[ i - 1 ].flags & FL_MORE ) ) )
{
int j;
/* Usually the attribute ID is the fieldID for the first entry,
however in some cases the attributeID is the same as the
fieldID and isn't specified until later on (denoted by the
fieldID being FIELDID_FOLLOWS), so we have to look ahead to
find it */
*attributeID = attributeInfoPtr[ i ].fieldID;
for( j = i + 1; *attributeID == FIELDID_FOLLOWS; j++ )
*attributeID = attributeInfoPtr[ j ].fieldID;
}
/* Check whether the field ID for this entry matches the one we want */
if( attributeInfoPtr[ i ].fieldID == fieldID )
{
ATTRIBUTE_INFO *altEncodingTable = \
( ATTRIBUTE_INFO * ) attributeInfoPtr[ i ].extraData;
/* If we're after a subfield match as well, try and match the
subfield */
if( subFieldID != CRYPT_ATTRIBUTE_NONE && altEncodingTable != NULL )
{
for( i = 0; altEncodingTable[ i ].fieldID != CRYPT_ERROR; i++ )
if( altEncodingTable[ i ].fieldID == subFieldID )
return( &altEncodingTable[ i ] );
return( NULL );
}
return( &attributeInfoPtr[ i ] );
}
}
return( NULL );
}
/****************************************************************************
* *
* Attribute Location/Cursor Movement Routines *
* *
****************************************************************************/
/* Find the start and end of an attribute from a field within the
attribute */
static ATTRIBUTE_LIST *findAttributeStart( const ATTRIBUTE_LIST *attributeListPtr )
{
CRYPT_ATTRIBUTE_TYPE attributeID;
if( attributeListPtr == NULL )
return( NULL );
attributeID = attributeListPtr->attributeID;
/* Move backwards until we find the start of the attribute */
while( attributeListPtr->prev != NULL && \
attributeListPtr->prev->attributeID == attributeID )
attributeListPtr = attributeListPtr->prev;
return( ( ATTRIBUTE_LIST * ) attributeListPtr );
}
static ATTRIBUTE_LIST *findAttributeEnd( const ATTRIBUTE_LIST *attributeListPtr )
{
CRYPT_ATTRIBUTE_TYPE attributeID;
if( attributeListPtr == NULL )
return( NULL );
attributeID = attributeListPtr->attributeID;
/* Move forwards until we find the start of the next attribute */
while( attributeListPtr->next != NULL && \
attributeListPtr->next->attributeID == attributeID )
attributeListPtr = attributeListPtr->next;
return( ( ATTRIBUTE_LIST * ) attributeListPtr );
}
/* Find an attribute in a list of certificate attributes by object identifier
(for blob-type attributes) or by field and subfield ID (for known
attributes), with extended handling for fields with default values */
ATTRIBUTE_LIST *findAttributeByOID( const ATTRIBUTE_LIST *attributeListPtr,
const BYTE *oid )
{
/* Find the position of this component in the list */
while( attributeListPtr != NULL && \
( sizeofOID( attributeListPtr->oid ) != sizeofOID( oid ) || \
memcmp( attributeListPtr->oid, oid, sizeofOID( oid ) ) ) )
attributeListPtr = attributeListPtr->next;
return( ( ATTRIBUTE_LIST * ) attributeListPtr );
}
ATTRIBUTE_LIST *findAttributeField( const ATTRIBUTE_LIST *attributeListPtr,
const CRYPT_ATTRIBUTE_TYPE fieldID,
const CRYPT_ATTRIBUTE_TYPE subFieldID )
{
/* Find the position of this component in the list */
while( attributeListPtr != NULL && \
attributeListPtr->fieldID != fieldID )
attributeListPtr = attributeListPtr->next;
if( subFieldID == CRYPT_ATTRIBUTE_NONE )
return( ( ATTRIBUTE_LIST * ) attributeListPtr );
/* Find the subfield in the field */
while( attributeListPtr != NULL && \
attributeListPtr->fieldID == fieldID )
{
if( attributeListPtr->subFieldID == subFieldID )
return( ( ATTRIBUTE_LIST * ) attributeListPtr );
attributeListPtr = attributeListPtr->next;
}
return( NULL );
}
ATTRIBUTE_LIST *findAttributeFieldEx( const ATTRIBUTE_LIST *attributeListPtr,
const CRYPT_ATTRIBUTE_TYPE fieldID )
{
static const ATTRIBUTE_LIST defaultField = DEFAULTFIELD_VALUE;
static const ATTRIBUTE_LIST completeAttribute = COMPLETEATTRIBUTE_VALUE;
const ATTRIBUTE_LIST *attributeListCursor = attributeListPtr;
const ATTRIBUTE_INFO *attributeInfoPtr;
const ATTRIBUTE_TYPE attributeType = ( fieldID >= CRYPT_FIRST_CMS ) ? \
ATTRIBUTE_CMS : ATTRIBUTE_CERTIFICATE;
CRYPT_ATTRIBUTE_TYPE attributeID;
/* Find the position of this component in the list */
while( attributeListCursor != NULL && \
attributeListCursor->fieldID != fieldID )
attributeListCursor = attributeListCursor->next;
if( attributeListCursor != NULL )
return( ( ATTRIBUTE_LIST * ) attributeListCursor );
/* The field isn't present in the list of attributes, check whether
the attribute itself is present and whether this field has a default
value */
attributeInfoPtr = fieldIDToAttribute( attributeType, fieldID,
CRYPT_ATTRIBUTE_NONE, &attributeID );
if( attributeInfoPtr == NULL )
/* There's no attribute containing this field, exit */
return( NULL );
/* Check whether any part of the attribute which contains the given
field is present in the list of attribute fields */
for( attributeListCursor = ( ATTRIBUTE_LIST * ) attributeListPtr;
attributeListCursor != NULL && \
attributeListCursor->attributeID != attributeID;
attributeListCursor = attributeListCursor->next );
if( attributeListCursor == NULL )
return( NULL );
/* Some other part of the attribute containing the given field is present
in the list. If this field wasn't found that could either be a
default value (in which case we return an entry which denotes that
this field is absent but has a default setting) or a field which
denotes an entire constructed attribute (in which case we return an
entry which denotes this) */
if( attributeInfoPtr->flags & FL_DEFAULT )
return( ( ATTRIBUTE_LIST * ) &defaultField );
if( attributeInfoPtr->fieldType == BER_SEQUENCE )
return( ( ATTRIBUTE_LIST * ) &completeAttribute );
return( NULL );
}
ATTRIBUTE_LIST *findAttribute( const ATTRIBUTE_LIST *attributeListPtr,
const CRYPT_ATTRIBUTE_TYPE fieldID )
{
const ATTRIBUTE_LIST *attributeListCursor = attributeListPtr;
/* Finding an overall attribute is a bit more complex than finding a
field since we may be given an attribute ID (which denotes the entire
attribute) or a field ID (which denotes one field in the attribute).
First we check for a match on the attribute ID */
while( attributeListCursor != NULL && \
attributeListCursor->attributeID != fieldID )
attributeListCursor = attributeListCursor->next;
if( attributeListCursor != NULL )
return( ( ATTRIBUTE_LIST * ) attributeListCursor );
/* It wasn't a (present) attribute ID, find the start of the attribute
which contains this field */
return( findAttributeStart( \
findAttributeField( attributeListPtr, fieldID,
CRYPT_ATTRIBUTE_NONE ) ) );
}
/* Get the default value for an optional field of an attribute */
int getDefaultFieldValue( const CRYPT_ATTRIBUTE_TYPE fieldID )
{
const ATTRIBUTE_INFO *attributeInfoPtr = \
fieldIDToAttribute( ( fieldID >= CRYPT_FIRST_CMS ) ? \
ATTRIBUTE_CMS : ATTRIBUTE_CERTIFICATE,
fieldID, CRYPT_ATTRIBUTE_NONE, NULL );
assert( isReadPtr( attributeInfoPtr, ATTRIBUTE_INFO ) );
return( ( int ) attributeInfoPtr->defaultValue );
}
/* Move the attribute cursor relative to the current cursor position. This
moves as far as possible in the direction given and then returns an
appropriate return code, either CRYPT_OK or CRYPT_ERROR_NOTFOUND if no
movement is possible. Note that it's possible to both return
CRYPT_ERROR_NOTFOUND and update the cursor, for example if we're halfway
through the first attribute then a position code of CRYPT_CURSOR_FIRST
will move to the start of the attribute, but the error will be returned to
indicate that it wasn't possible to move back before the current
attribute */
int moveAttributeCursor( ATTRIBUTE_LIST **currentCursor,
const CRYPT_ATTRIBUTE_TYPE certInfoType,
const int position )
{
const CRYPT_ATTRIBUTE_TYPE attributeID = ( *currentCursor )->attributeID;
const ATTRIBUTE_LIST *newCursor = *currentCursor, *lastCursor = NULL;
const BOOLEAN absMove = ( position == CRYPT_CURSOR_FIRST || \
position == CRYPT_CURSOR_LAST ) ? TRUE : FALSE;
int count;
assert( certInfoType == CRYPT_CERTINFO_CURRENT_EXTENSION || \
certInfoType == CRYPT_CERTINFO_CURRENT_FIELD || \
certInfoType == CRYPT_CERTINFO_CURRENT_COMPONENT );
assert( position <= CRYPT_CURSOR_FIRST && \
position >= CRYPT_CURSOR_LAST );
/* Set the amount we want to move by based on the position code. This
means we can handle the movement in a simple while loop instead of
having to special-case it for moves by one item */
count = absMove ? INT_MAX : 1;
/* Moving by field or component is relatively simple. For fields we move
backwards or forwards until we either run out of fields or the next
field belongs to a different attribute. For components we move
similarly, except that we stop when we reach a field whose attribute
type, field type, and subfield type don't match the current one */
if( certInfoType == CRYPT_CERTINFO_CURRENT_FIELD )
{
if( position == CRYPT_CURSOR_FIRST || position == CRYPT_CURSOR_PREVIOUS )
while( count-- && newCursor->prev != NULL && \
newCursor->prev->attributeID == attributeID )
newCursor = newCursor->prev;
else
while( count-- && newCursor->next != NULL && \
newCursor->next->attributeID == attributeID )
newCursor = newCursor->next;
if( !absMove && *currentCursor == newCursor )
return( CRYPT_ERROR_NOTFOUND );
*currentCursor = ( ATTRIBUTE_LIST * ) newCursor;
return( CRYPT_OK );
}
if( certInfoType == CRYPT_CERTINFO_CURRENT_COMPONENT )
{
const CRYPT_ATTRIBUTE_TYPE fieldID = ( *currentCursor )->fieldID;
const CRYPT_ATTRIBUTE_TYPE subFieldID = ( *currentCursor )->subFieldID;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?