certext.c
来自「提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发」· C语言 代码 · 共 1,330 行 · 第 1/4 页
C
1,330 行
if( !isprint( ch ) )
isOK = FALSE;
if( attributeInfoPtr->fieldType == BER_STRING_PRINTABLE && \
( ( ch >= '!' && ch <= '&' ) || ch == '*' || ch == ';' || \
ch == '<' || ch == '>' || ch == '@' || \
( ch >= '[' && ch <= '`' ) || ch >= '{' ) )
isOK = FALSE;
if( !isOK )
{
if( errorType != NULL )
*errorType = CRYPT_ERRTYPE_ATTR_VALUE;
return( CRYPT_ARGERROR_STR1 );
}
}
}
return( CRYPT_OK );
}
int addAttributeField( ATTRIBUTE_LIST **attributeListPtr,
const CRYPT_ATTRIBUTE_TYPE fieldID,
const CRYPT_ATTRIBUTE_TYPE subFieldID,
const void *data, const int dataLength,
const int flags, CRYPT_ATTRIBUTE_TYPE *errorLocus,
CRYPT_ERRTYPE_TYPE *errorType )
{
const ATTRIBUTE_TYPE attributeType = ( fieldID >= CRYPT_FIRST_CMS ) ? \
ATTRIBUTE_CMS : ATTRIBUTE_CERTIFICATE;
CRYPT_ATTRIBUTE_TYPE attributeID;
const ATTRIBUTE_INFO *attributeInfoPtr = fieldIDToAttribute( attributeType,
fieldID, subFieldID, &attributeID );
ATTRIBUTE_LIST *newElement, *insertPoint, *prevElement = NULL;
int status;
assert( isWritePtr( attributeListPtr, ATTRIBUTE_LIST * ) );
assert( dataLength == CRYPT_UNUSED || \
( dataLength > 0 && dataLength <= MAX_ATTRIBUTE_SIZE ) );
assert( dataLength == CRYPT_UNUSED || \
!checkBadPtrRead( data, dataLength ) );
assert( !( flags & ATTR_FLAG_INVALID ) );
assert( isReadPtr( attributeInfoPtr, ATTRIBUTE_INFO ) );
/* Check the field's validity if necessary */
status = checkAttributeField( *attributeListPtr, attributeInfoPtr,
fieldID, subFieldID, data, dataLength,
flags, errorType );
if( cryptStatusError( status ) )
{
if( errorType != NULL && cryptStatusError( *errorType ) )
/* If we encountered an error which sets the error type, record
the locus */
*errorLocus = fieldID;
return( status );
}
/* Find the location at which to insert this attribute field (this
assumes that the fieldIDs are defined in sorted order) */
insertPoint = *attributeListPtr;
while( insertPoint != NULL && \
insertPoint->fieldID != CRYPT_ATTRIBUTE_NONE && \
insertPoint->fieldID <= fieldID )
{
/* If it's a composite field which can have multiple fields with the
same field ID (eg a GeneralName), exit if the overall field ID is
greater (the component belongs to a different field entirely) or
if the field ID is the same and the subfield ID is greater (if
the component belongs to the same field) */
if( subFieldID != CRYPT_ATTRIBUTE_NONE && \
insertPoint->fieldID == fieldID && \
insertPoint->subFieldID > subFieldID )
break;
prevElement = insertPoint;
insertPoint = insertPoint->next;
}
insertPoint = prevElement;
/* Allocate memory for the new element and copy the information across.
If it's a simple type we can assign it to the simple value in the
element itself, otherwise we either copy it into the storage in the
element or allocate seperate storage and copy it into that. Something
which encodes to NULL isn't really a numeric type, but we class it as
such so that any attempt to read it returns CRYPT_UNUSED as the value */
if( ( newElement = ( ATTRIBUTE_LIST * ) malloc( sizeof( ATTRIBUTE_LIST ) ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
memset( newElement, 0, sizeof( ATTRIBUTE_LIST ) );
newElement->attributeID = attributeID;
newElement->fieldID = fieldID;
newElement->subFieldID = subFieldID;
newElement->flags = flags;
newElement->fieldType = attributeInfoPtr->fieldType;
switch( attributeInfoPtr->fieldType )
{
case BER_INTEGER:
case BER_ENUMERATED:
case BER_BITSTRING:
case BER_BOOLEAN:
case BER_NULL:
case FIELDTYPE_CHOICE:
newElement->value = *( ( int * ) data );
if( attributeInfoPtr->fieldType == BER_BOOLEAN )
/* Force it to the correct type if it's a boolean */
newElement->value = ( newElement->value ) ? TRUE : FALSE;
if( attributeInfoPtr->fieldType == FIELDTYPE_CHOICE )
/* For encoding purposes the subfield ID is set to the ID of
the CHOICE selection */
newElement->subFieldID = newElement->value;
break;
case BER_OBJECT_IDENTIFIER:
/* If it's a BER/DER-encoded OID copy it in as is, otherwise
convert it from the text form */
if( ( ( BYTE * ) data )[ 0 ] == BER_OBJECT_IDENTIFIER )
{
memcpy( newElement->smallData, data, dataLength );
newElement->dataLength = dataLength;
}
else
newElement->dataLength = textToOID( data, dataLength,
newElement->smallData );
break;
case 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 */
if( *( ( int * ) data ) != CRYPT_UNUSED )
newElement->data = ( void * ) data;
break;
case FIELDTYPE_IDENTIFIER:
/* This is a placeholder entry with no explicit value */
newElement->value = CRYPT_UNUSED;
break;
default:
assert( dataLength > 0 );
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( attributeListPtr, insertPoint,
newElement, newElement );
return( CRYPT_OK );
}
/* Copy an attribute from one attribute list to another. This is an all-or-
nothing copy in that it either copies a complete attribute or nothing at
all */
static int copyAttributeField( ATTRIBUTE_LIST **destAttributeField,
const ATTRIBUTE_LIST *srcAttributeField )
{
ATTRIBUTE_LIST *newElement;
int status = CRYPT_OK;
assert( isWritePtr( destAttributeField, ATTRIBUTE_LIST * ) );
assert( isReadPtr( srcAttributeField, ATTRIBUTE_LIST ) );
/* Allocate memory for the new element and copy the information across.
If it's a simple type we can assign it to the simple value in the
element itself, otherwise we either copy into the storage in the
element or allocate seperate storage and copy it into that */
*destAttributeField = NULL;
if( ( newElement = ( ATTRIBUTE_LIST * ) malloc( sizeof( ATTRIBUTE_LIST ) ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
memcpy( newElement, srcAttributeField, sizeof( ATTRIBUTE_LIST ) );
if( srcAttributeField->dataLength > CRYPT_MAX_TEXTSIZE )
{
/* If the payload doesn't fit into the attribute structure, copy the
separate data payload across */
if( ( newElement->data = malloc( srcAttributeField->dataLength ) ) == NULL )
status = CRYPT_ERROR_MEMORY;
else
memcpy( newElement->data, srcAttributeField->data,
srcAttributeField->dataLength );
}
else
if( srcAttributeField->fieldType == FIELDTYPE_DN )
/* If the field contains a DN, copy the DN across */
status = copyDN( ( void ** ) &newElement->data,
srcAttributeField->data );
if( cryptStatusError( status ) )
{
assert( newElement->data == NULL );
free( newElement );
return( status );
}
newElement->next = newElement->prev = NULL;
*destAttributeField = newElement;
return( CRYPT_OK );
}
static int copyAttribute( ATTRIBUTE_LIST **destListHeadPtr,
const ATTRIBUTE_LIST *srcListPtr,
const BOOLEAN subjectToIssuer )
{
const CRYPT_ATTRIBUTE_TYPE attributeID = srcListPtr->attributeID;
CRYPT_ATTRIBUTE_TYPE newAttributeID = attributeID, newFieldID = attributeID;
ATTRIBUTE_LIST *newAttributeListHead = NULL, *newAttributeListTail;
ATTRIBUTE_LIST *insertPoint, *prevElement = NULL;
assert( isWritePtr( destListHeadPtr, ATTRIBUTE_LIST * ) );
assert( isReadPtr( srcListPtr, ATTRIBUTE_LIST ) );
/* If we're copying from an issuer to a subject attribute list and the
field is an altName or keyIdentifier, change the field type from
issuer.subjectAltName to subject.issuerAltName or
issuer.subjectKeyIdentifier to subject.authorityKeyIdentifier */
if( subjectToIssuer )
{
if( attributeID == CRYPT_CERTINFO_SUBJECTALTNAME )
newAttributeID = newFieldID = CRYPT_CERTINFO_ISSUERALTNAME;
if( attributeID == CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER )
{
newAttributeID = CRYPT_CERTINFO_AUTHORITYKEYIDENTIFIER;
newFieldID = CRYPT_CERTINFO_AUTHORITY_KEYIDENTIFIER;
}
}
/* Find the location at which to insert this attribute. For now we
assume that the fieldIDs are defined in sorted order, we may need to
change this and add internal mapping if new fieldIDs are added out of
order */
for( insertPoint = *destListHeadPtr;
insertPoint != NULL && insertPoint->attributeID < newAttributeID && \
insertPoint->fieldID != CRYPT_ATTRIBUTE_NONE;
insertPoint = insertPoint->next )
prevElement = insertPoint;
insertPoint = prevElement;
/* Build a new attribute list containing the attribute fields */
while( srcListPtr != NULL && srcListPtr->attributeID == attributeID )
{
ATTRIBUTE_LIST *newAttributeField;
int status;
/* Copy the field across, append it to the new attribute list, and
adjust the type for issuer->subject copying if necessary */
status = copyAttributeField( &newAttributeField, srcListPtr );
if( cryptStatusError( status ) )
{
deleteAttributes( &newAttributeListHead );
return( CRYPT_ERROR_MEMORY );
}
if( newAttributeListHead == NULL )
newAttributeListHead = newAttributeListTail = newAttributeField;
else
{
newAttributeListTail->next = newAttributeField;
newAttributeField->prev = newAttributeListTail;
newAttributeListTail = newAttributeField;
}
if( newAttributeID != attributeID )
{
newAttributeField->attributeID = newAttributeID;
newAttributeField->fieldID = newFieldID;
}
/* Move on to the next field */
srcListPtr = srcListPtr->next;
}
/* Link the new list into the existing list at the appropriate position */
insertListElements( destListHeadPtr, insertPoint, newAttributeListHead,
newAttributeListTail );
return( CRYPT_OK );
}
/* Copy a complete attribute list */
int copyAttributes( ATTRIBUTE_LIST **destListHeadPtr,
ATTRIBUTE_LIST *srcListPtr,
CRYPT_ATTRIBUTE_TYPE *errorLocus,
CRYPT_ERRTYPE_TYPE *errorType )
{
ATTRIBUTE_LIST *attributeListCursor = srcListPtr;
assert( isWritePtr( destListHeadPtr, ATTRIBUTE_LIST * ) );
assert( isReadPtr( srcListPtr, ATTRIBUTE_LIST ) );
/* Make a first pass down the list checking that the attribute to copy
isn't already present, first for recognised attributes and then for
unrecognised ones. We have to do this separately since once we begin
the copy process it's rather hard to undo it. Note that in theory
there are some attributes which can have multiple instances of a field
present, which means we could allow them to appear in both the source
and destination lists, however if this occurs it's more likely to be
an error than a desire to merge two disparate collections of
attributes */
while( attributeListCursor != NULL && \
!isBlobAttribute( attributeListCursor ) )
{
if( findAttributeField( *destListHeadPtr,
attributeListCursor->fieldID, CRYPT_ATTRIBUTE_NONE ) != NULL )
{
*errorLocus = attributeListCursor->fieldID;
*errorType = CRYPT_ERRTYPE_ATTR_PRESENT;
return( CRYPT_ERROR_DUPLICATE );
}
attributeListCursor = attributeListCursor->next;
}
while( attributeListCursor != NULL )
{
if( findAttributeByOID( *destListHeadPtr, attributeListCursor->oid ) != NULL )
{
/* We can't set the locus for blob-type attributes since it's not
a known attribute */
*errorLocus = CRYPT_ATTRIBUTE_NONE;
*errorType = CRYPT_ERRTYPE_ATTR_PRESENT;
return( CRYPT_ERROR_DUPLICATE );
}
attributeListCursor = attributeListCursor->next;
}
/* Make a second pass copying everything across */
while( srcListPtr != NULL && !isBlobAttribute( srcListPtr ) )
{
CRYPT_ATTRIBUTE_TYPE attributeID = srcListPtr->attributeID;
int status;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?