certext.c
来自「提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发」· C语言 代码 · 共 1,330 行 · 第 1/4 页
C
1,330 行
if( position == CRYPT_CURSOR_FIRST || position == CRYPT_CURSOR_PREVIOUS )
while( count-- && newCursor->prev != NULL && \
newCursor->prev->attributeID == attributeID && \
newCursor->prev->fieldID == fieldID && \
newCursor->prev->subFieldID == subFieldID )
newCursor = newCursor->prev;
else
while( count-- && newCursor->next != NULL && \
newCursor->next->attributeID == attributeID && \
newCursor->next->fieldID == fieldID && \
newCursor->next->subFieldID == subFieldID )
newCursor = newCursor->next;
if( !absMove && *currentCursor == newCursor )
return( CRYPT_ERROR_NOTFOUND );
*currentCursor = ( ATTRIBUTE_LIST * ) newCursor;
return( CRYPT_OK );
}
/* Moving by attribute is a bit more complex. First we find the start or
end of the current attribute, if there's another attribute before or
after it move back/forwards into that attribute and find the start of
that. This has the effect of moving us from anywhere in the current
attribute to the start of the preceding or following attribute.
Finally, we repeat this as required */
if( position == CRYPT_CURSOR_FIRST || position == CRYPT_CURSOR_PREVIOUS )
while( count-- && newCursor != NULL )
{
lastCursor = newCursor;
newCursor = findAttributeStart( findAttributeStart( newCursor )->prev );
}
else
while( count-- && newCursor != NULL && \
newCursor->attributeID != CRYPT_ATTRIBUTE_NONE )
{
lastCursor = newCursor;
newCursor = findAttributeEnd( newCursor )->next;
}
/* We've gone as far as we can. If the new cursor is NULL, we've reached
the start or end of the attribute list, in case we haven't moved at all
we call findAttributeStart() to move to the first field. If the new
cursor isn't NULL, it's located on the next or previous attribute */
if( newCursor == NULL )
*currentCursor = findAttributeStart( lastCursor );
else
*currentCursor = ( ATTRIBUTE_LIST * ) newCursor;
if( *currentCursor == NULL )
/* Positioning in null attribute lists is always unsuccessful */
return( CRYPT_ERROR_NOTFOUND );
if( position == CRYPT_CURSOR_FIRST || position == CRYPT_CURSOR_LAST )
/* Absolute positioning is always successful */
return( CRYPT_OK );
return( ( ( *currentCursor )->attributeID == attributeID ) ? \
CRYPT_ERROR_NOTFOUND : CRYPT_OK );
}
/****************************************************************************
* *
* Attribute Management Routines *
* *
****************************************************************************/
/* Insert elements into an attribute list after the given insertion point */
static void insertListElements( ATTRIBUTE_LIST **listHeadPtr,
ATTRIBUTE_LIST *insertPoint,
ATTRIBUTE_LIST *newStartElement,
ATTRIBUTE_LIST *newEndElement )
{
assert( isWritePtr( listHeadPtr, ATTRIBUTE_LIST * ) );
/* If it's an empty list, make this the new list */
if( *listHeadPtr == NULL )
{
*listHeadPtr = newStartElement;
return;
}
assert( isWritePtr( *listHeadPtr, ATTRIBUTE_LIST ) );
assert( isWritePtr( newStartElement, ATTRIBUTE_LIST ) );
assert( isWritePtr( newEndElement, ATTRIBUTE_LIST ) );
/* If we're inserting at the start of the list, make this the new first
element */
if( insertPoint == NULL )
{
/* Insert the element at the start of the list */
newEndElement->next = *listHeadPtr;
( *listHeadPtr )->prev = newEndElement;
*listHeadPtr = newStartElement;
return;
}
assert( isWritePtr( insertPoint, ATTRIBUTE_LIST ) );
/* Insert the element in the middle or end of the list. Update the links
for the next element */
newEndElement->next = insertPoint->next;
if( insertPoint->next != NULL )
insertPoint->next->prev = newEndElement;
/* Update the links for the previous element */
insertPoint->next = newStartElement;
newStartElement->prev = insertPoint;
}
/* Add a blob-type attribute to a list of attributes */
int addAttribute( const ATTRIBUTE_TYPE attributeType,
ATTRIBUTE_LIST **listHeadPtr, const BYTE *oid,
const BOOLEAN criticalFlag, const void *data,
const int dataLength )
{
ATTRIBUTE_LIST *newElement, *insertPoint;
assert( isWritePtr( listHeadPtr, ATTRIBUTE_LIST * ) );
assert( isReadPtr( oid, 3 ) );
assert( criticalFlag == TRUE || criticalFlag == FALSE );
assert( !checkBadPtrRead( data, dataLength ) );
assert( dataLength > 0 && dataLength <= MAX_ATTRIBUTE_SIZE );
/* If this attribute type is already handled as a non-blob attribute,
don't allow it to be added as a blob as well. This avoids problems
with the same attribute being added twice, once as a blob and once as
a non-blob. In addition it forces the caller to use the (recommended)
normal attribute handling mechanism which allows for proper type
checking */
if( oidToAttribute( attributeType, oid ) != NULL )
return( CRYPT_ERROR_PERMISSION );
/* Find the correct place in the list to insert the new element */
if( *listHeadPtr != NULL )
{
ATTRIBUTE_LIST *prevElement = NULL;
for( insertPoint = *listHeadPtr; insertPoint != NULL;
insertPoint = insertPoint->next )
{
/* Make sure this blob attribute isn't already present */
if( insertPoint->attributeID != CRYPT_ATTRIBUTE_NONE && \
sizeofOID( insertPoint->oid ) == sizeofOID( oid ) && \
!memcmp( insertPoint->oid, oid, sizeofOID( oid ) ) )
return( CRYPT_ERROR_INITED );
prevElement = insertPoint;
}
insertPoint = prevElement;
}
/* Allocate memory for the new element and copy the information across */
if( ( newElement = ( ATTRIBUTE_LIST * ) malloc( sizeof( ATTRIBUTE_LIST ) ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
memset( newElement, 0, sizeof( ATTRIBUTE_LIST ) );
memcpy( newElement->oid, oid, sizeofOID( oid ) );
newElement->flags = criticalFlag ? ATTR_FLAG_CRITICAL : ATTR_FLAG_NONE;
if( dataLength <= CRYPT_MAX_TEXTSIZE )
memcpy( newElement->smallData, data, dataLength );
else
{
if( ( newElement->data = malloc( dataLength ) ) == NULL )
{
free( newElement );
return( CRYPT_ERROR_MEMORY );
}
memcpy( newElement->data, data, dataLength );
}
newElement->dataLength = dataLength;
insertListElements( listHeadPtr, insertPoint, newElement, newElement );
return( CRYPT_OK );
}
/* Add an attribute field at the appropriate location to a list of
attributes after checking its validity */
static int checkAttributeField( const ATTRIBUTE_LIST *attributeListPtr,
const ATTRIBUTE_INFO *attributeInfoPtr,
const CRYPT_ATTRIBUTE_TYPE fieldID,
const CRYPT_ATTRIBUTE_TYPE subFieldID,
const void *data, const int dataLength,
const int flags,
CRYPT_ERRTYPE_TYPE *errorType )
{
const ATTRIBUTE_TYPE attributeType = ( fieldID >= CRYPT_FIRST_CMS ) ? \
ATTRIBUTE_CMS : ATTRIBUTE_CERTIFICATE;
ATTRIBUTE_LIST *attributeListSearchPtr;
assert( isReadPtr( attributeInfoPtr, ATTRIBUTE_INFO ) );
assert( dataLength == CRYPT_UNUSED || \
( dataLength > 0 && dataLength <= MAX_ATTRIBUTE_SIZE ) );
assert( dataLength == CRYPT_UNUSED || \
!checkBadPtrRead( data, dataLength ) );
assert( !( flags & ATTR_FLAG_INVALID ) );
/* Make sure that a valid field has been specified, and that this field
isn't already present as a non-default entry unless it's a field for
which multiple values are allowed */
if( attributeInfoPtr == NULL )
return( CRYPT_ARGERROR_VALUE );
attributeListSearchPtr = findAttributeField( attributeListPtr, fieldID,
subFieldID );
if( attributeListSearchPtr != NULL && \
!( ( attributeInfoPtr->flags & FL_MULTIVALUED ) || \
( flags & ATTR_FLAG_MULTIVALUED ) ) )
{
if( errorType != NULL )
*errorType = CRYPT_ERRTYPE_ATTR_PRESENT;
return( CRYPT_ERROR_INITED );
}
/* If it's a blob field, don't do any type checking. This is a special
case which differs from FIELDTYPE_BLOB in that it corresponds to an
ASN.1 value which is mis-encoded by one or more implementations so we
have to accept absolutely anything at this point */
if( flags & ATTR_FLAG_BLOB )
return( CRYPT_OK );
/* If it's an identifier or special-case field, make sure all parameters
are correct */
if( attributeInfoPtr->fieldType == FIELDTYPE_IDENTIFIER )
{
assert( dataLength == CRYPT_UNUSED );
if( *( ( int * ) data ) != CRYPT_UNUSED )
return( CRYPT_ARGERROR_NUM1 );
return( CRYPT_OK );
}
if( attributeInfoPtr->fieldType == FIELDTYPE_DN )
{
/* When creating a new cert, this is a placeholder to indicate that
a DN structure is being instantiated. When reading an encoded
cert, this is the decoded DN structure */
assert( dataLength == CRYPT_UNUSED );
return( CRYPT_OK );
}
/* If it's an OID, convert it to a binary OID (which performs a syntax
check on the OID) */
if( attributeInfoPtr->fieldType == BER_OBJECT_IDENTIFIER )
{
const BYTE *oidPtr = data;
BYTE binaryOID[ MAX_OID_SIZE ];
/* If it's a BER/DER-encoded OID, make sure it's valid ASN.1 */
if( oidPtr[ 0 ] == BER_OBJECT_IDENTIFIER )
{
if( oidPtr[ 1 ] == dataLength - 2 )
return( CRYPT_OK );
}
else
/* It's a text OID, check the syntax and make sure the length
is valid */
if( textToOID( data, dataLength, binaryOID ) )
return( CRYPT_OK );
if( errorType != NULL )
*errorType = CRYPT_ERRTYPE_ATTR_VALUE;
return( CRYPT_ARGERROR_STR1 );
}
/* If it's an integer type, type check it */
if( attributeInfoPtr->fieldType == BER_INTEGER || \
attributeInfoPtr->fieldType == BER_ENUMERATED || \
attributeInfoPtr->fieldType == BER_BITSTRING || \
attributeInfoPtr->fieldType == BER_BOOLEAN || \
attributeInfoPtr->fieldType == BER_NULL || \
attributeInfoPtr->fieldType == FIELDTYPE_CHOICE )
{
int value = *( ( int * ) data );
assert( dataLength == CRYPT_UNUSED );
/* BOOLEAN data is accepted as zero/nonzero so it's always valid */
if( attributeInfoPtr->fieldType == BER_BOOLEAN )
return( CRYPT_OK );
/* Check that the data size and range is valid */
if( value < attributeInfoPtr->lowRange || \
value > attributeInfoPtr->highRange )
{
if( errorType != NULL )
*errorType = CRYPT_ERRTYPE_ATTR_VALUE;
return( CRYPT_ARGERROR_NUM1 );
}
return( CRYPT_OK );
}
/* Type check the value */
if( dataLength < attributeInfoPtr->lowRange || \
dataLength > attributeInfoPtr->highRange )
{
if( errorType != NULL )
*errorType = CRYPT_ERRTYPE_ATTR_SIZE;
return( CRYPT_ARGERROR_NUM1 );
}
if( attributeInfoPtr->fieldType == FIELDTYPE_BLOB )
{
/* If it's a blob field, make sure it's a valid ASN.1 object */
if( cryptStatusError( getObjectLength( data, dataLength ) ) )
{
if( errorType != NULL )
*errorType = CRYPT_ERRTYPE_ATTR_VALUE;
return( CRYPT_ARGERROR_STR1 );
}
}
if( attributeInfoPtr->fieldType == BER_STRING_NUMERIC )
{
const char *dataPtr = data;
int i;
for( i = 0; i < dataLength; i++ )
if( !isdigit( dataPtr[ i ] ) )
{
if( errorType != NULL )
*errorType = CRYPT_ERRTYPE_ATTR_VALUE;
return( CRYPT_ARGERROR_STR1 );
}
}
if( attributeInfoPtr->fieldType == BER_STRING_IA5 || \
attributeInfoPtr->fieldType == BER_STRING_ISO646 || \
attributeInfoPtr->fieldType == BER_STRING_PRINTABLE )
{
const char *dataPtr = data;
BOOLEAN isOK = TRUE;
int i;
for( i = 0; i < dataLength; i++ )
{
const char ch = dataPtr[ i ];
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?