📄 certexrd.c
字号:
TRACE_FIELDTYPE( attributeInfoPtr, setofStackPos );
status = addAttributeField( attributeListPtrPtr,
attributeInfoPtr->fieldID, CRYPT_ATTRIBUTE_NONE,
&dummy, CRYPT_UNUSED, flags, errorLocus,
errorType );
if( status == CRYPT_ERROR_INITED )
status = CRYPT_OK;
if( cryptStatusError( status ) )
return( fieldErrorReturn( errorLocus,
errorType, CRYPT_ERROR_BADDATA,
attributeInfoPtr->fieldID ) );
}
/* Reset the attribute info position in preparation for
the next value and continue */
attributeInfoPtr = setofInfoPtr->infoStart + 1;
continue;
}
}
}
/* Subtyped field: Switch to the new encoding table */
if( attributeInfoPtr->fieldType == FIELDTYPE_SUBTYPED )
{
setofInfoPtr->subtypeParent = attributeInfoPtr->fieldID;
setofInfoPtr->inheritedFlags = \
( attributeInfoPtr->flags & FL_MULTIVALUED ) ? \
ATTR_FLAG_MULTIVALUED : ATTR_FLAG_NONE;
/* If the subtype ends once the current SET/SEQUENCE ends,
remember this so that we return to the main type when
appropriate */
if( ( attributeInfoPtr->flags & FL_SEQEND_MASK ) || \
!( attributeInfoPtr->flags & FL_MORE ) )
setofInfoPtr->subTyped = TRUE;
/* Switch to the new state */
attributeInfoPtr = ( ATTRIBUTE_INFO * ) attributeInfoPtr->extraData;
}
/* CHOICE (of object identifiers): Read a single OID from a
selection */
if( attributeInfoPtr->fieldType == FIELDTYPE_CHOICE )
{
const ATTRIBUTE_INFO *extraDataPtr = attributeInfoPtr->extraData;
/* Needed because ->extraData is read-only */
status = readIdentifierFields( stream, attributeListPtrPtr,
&extraDataPtr, flags, attributeInfoPtr->fieldID,
errorLocus, errorType );
if( cryptStatusError( status ) )
return( fieldErrorReturn( errorLocus, errorType,
CRYPT_ERROR_BADDATA,
attributeInfoPtr->fieldID ) );
goto continueDecoding;
}
/* Identifier field: Read a sequence of one or more { oid, value }
fields and continue */
if( attributeInfoPtr->fieldType == FIELDTYPE_IDENTIFIER )
{
status = readIdentifierFields( stream, attributeListPtrPtr,
&attributeInfoPtr, flags,
CRYPT_ATTRIBUTE_NONE, errorLocus, errorType );
if( cryptStatusError( status ) )
return( fieldErrorReturn( errorLocus, errorType,
CRYPT_ERROR_BADDATA,
attributeInfoPtr->fieldID ) );
goto continueDecoding;
}
/* Non-encoding field: Check that it matches the required value and
continue */
if( attributeInfoPtr->flags & FL_NONENCODING )
{
BYTE data[ 64 ];
int dataLength;
/* Read the data and continue. We don't check its value or set
specific error information for reasons given under the SET-OF
handling code above (value check) and optional field code below
(error locus set) */
TRACE_FIELDTYPE( attributeInfoPtr, setofStackPos );
status = readRawObject( stream, data, &dataLength, 64, CRYPT_UNUSED );
if( cryptStatusError( status ) )
return( status );
goto continueDecoding;
}
/* Extract various pieces of information from the attribute field
definition */
isTagged = ( attributeInfoPtr->fieldEncodedType ) ? TRUE : FALSE;
tag = ( isTagged ) ? attributeInfoPtr->fieldEncodedType : \
attributeInfoPtr->fieldType;
if( isTagged && ( attributeInfoPtr->fieldType == BER_SEQUENCE ||
attributeInfoPtr->fieldType == BER_SET ||
attributeInfoPtr->fieldType == FIELDTYPE_DN ||
( attributeInfoPtr->flags & FL_EXPLICIT ) ) )
/* If it's an implictly tagged sequence/set then it's constructed */
tag |= BER_CONSTRUCTED;
/* Optional field: Check whether it's present and if it isn't, move
on to the next field */
if( ( attributeInfoPtr->flags & FL_OPTIONAL ) && \
peekTag( stream ) != tag )
{
/* If it's a field with a default value, add that value. This
isn't needed for cryptlib's own use since it knows the default
values for fields, but can cause confusion for the caller if
all fields in an attribute have default values because the
attribute will appear to disappear when it's read in as no
fields are ever added */
if( attributeInfoPtr->flags & FL_DEFAULT )
{
const int value = ( int ) attributeInfoPtr->defaultValue;
status = addAttributeField( attributeListPtrPtr,
attributeInfoPtr->fieldID, CRYPT_ATTRIBUTE_NONE,
&value, CRYPT_UNUSED, flags, NULL, NULL );
if( cryptStatusError( status ) )
/* This is a field contributed from internal data so we
don't try and get an error locus or value for it
since this would only confuse the caller */
return( CRYPT_ERROR_BADDATA );
}
/* Skip to the end of the item and continue */
attributeInfoPtr = findItemEnd( attributeInfoPtr, 0 );
goto continueDecoding;
}
/* Print a trace of what we're processing. Everything before this
point does its own special-case tracing if required, so we don't
trace before we get here to prevent displaying duplicate/
misleading information */
TRACE_FIELDTYPE( attributeInfoPtr, setofStackPos );
/* Explicitly tagged field: Read the explicit wrapper and make sure
that it matches what we're expecting */
if( attributeInfoPtr->flags & FL_EXPLICIT )
{
assert( isTagged );
assert( MAKE_CTAG( tag ) == tag ); /* Always constructed */
status = readConstructed( stream, NULL, tag );
if( cryptStatusError( status ) )
return( fieldErrorReturn( errorLocus, errorType, status,
attributeInfoPtr->fieldID ) );
/* We've processed the explicit wrappper, we're now on the actual
tag */
tag = attributeInfoPtr->fieldType;
}
/* Blob field or DN: We don't try and interpret blobs in any way, and
DNs are a composite structure read as a complete unit by the lower-
level code */
if( attributeInfoPtr->fieldType == FIELDTYPE_BLOB || \
attributeInfoPtr->fieldType == FIELDTYPE_DN )
{
status = readAttributeField( stream, attributeListPtrPtr,
attributeInfoPtr,
setofInfoPtr->subtypeParent,
flags | setofInfoPtr->inheritedFlags,
errorLocus, errorType );
if( cryptStatusError( status ) )
/* Adding complex attributes such as DNs can return detailed
error codes that report the exact parameter that was wrong,
we don't need this much detail so we convert a parameter
error into a more general bad data status */
return( fieldErrorReturn( errorLocus, errorType,
cryptArgError( status ) ? \
CRYPT_ERROR_BADDATA : status,
attributeInfoPtr->fieldID ) );
goto continueDecoding;
}
/* Standard field: Read the tag for the field and make sure that it
matches what we're expecting */
if( peekTag( stream ) != tag )
return( fieldErrorReturn( errorLocus, errorType,
CRYPT_ERROR_BADDATA,
attributeInfoPtr->fieldID ) );
/* SET/SET OF/SEQUENCE/SEQUENCE OF start: Record its end position,
stack the current processing state, and continue */
if( attributeInfoPtr->fieldType == BER_SEQUENCE || \
attributeInfoPtr->fieldType == BER_SET || \
( attributeInfoPtr->flags & FL_SETOF ) )
{
void *objectPtr;
int setofLength, setEndEOC = 0;
assert( !( attributeInfoPtr->flags & FL_EXPLICIT ) );
/* Determine the length and start position of the SET OF items.
Some broken Verisign certs suddenly break into BER inside the
cert policy extension, so if the length evaluates to zero we
have to determine it by burrowing into the ASN.1 */
objectPtr = sMemBufPtr( stream );
if( attributeInfoPtr->fieldEncodedType )
status = readConstructed( stream, &setofLength,
attributeInfoPtr->fieldEncodedType );
else
if( attributeInfoPtr->fieldType == BER_SET )
status = readSet( stream, &setofLength );
else
status = readSequence( stream, &setofLength );
#if 0 /* 22/11/03 Removed since these Verisign certs have now expired */
if( cryptStatusOK( status ) && setofLength == CRYPT_UNUSED )
{
/* Get the overall length without the tag + indef.length */
status = setofLength = \
getObjectLength( objectPtr, sMemDataLeft( stream ) );
setofLength -= 2;
setEndEOC = 2; /* Two bytes of EOC at end of object */
}
#endif /* 0 */
if( cryptStatusError( status ) )
return( fieldErrorReturn( errorLocus, errorType, status,
attributeInfoPtr->fieldID ) );
/* When processing a SET/SEQUENCE with default values for the
elements, the result may be a zero-length object, in which
case we don't take any action */
if( setofLength > 0 )
{
const CRYPT_ATTRIBUTE_TYPE oldSubtypeParent = \
setofInfoPtr->subtypeParent;
const int oldInheritedFlags = setofInfoPtr->inheritedFlags;
/* Remember where the SET/SEQUENCE ends. In addition if
this is a SET OF/SEQUENCE OF, remember this as a restart
point for when we're parsing the next item in the
SET/SEQUENCE OF */
setofInfoPtr = stackSetofState( setofStack, &setofStackPos );
setofInfoPtr->infoStart = attributeInfoPtr;
if( attributeInfoPtr->flags & FL_SETOF )
setofInfoPtr->restartPoint = TRUE;
setofInfoPtr->subtypeParent = oldSubtypeParent;
setofInfoPtr->inheritedFlags = oldInheritedFlags;
setofInfoPtr->endPos = stell( stream ) + setofLength - \
setEndEOC;
#if 0 /* 22/11/03 Removed since these Verisign certs have now expired */
setofInfoPtr->endEOC = setEndEOC ? TRUE : FALSE;
#endif /* 0 */
}
goto continueDecoding;
}
/* We've checked the tag, skip it. We do this at this level rather
than in readAttributeField() because it doesn't know about
context-specific tagging requirements */
readTag( stream );
/* Standard field, read the field data */
status = readAttributeField( stream, attributeListPtrPtr,
attributeInfoPtr,
setofInfoPtr->subtypeParent,
flags | setofInfoPtr->inheritedFlags,
errorLocus, errorType );
if( cryptStatusError( status ) )
/* Adding invalid attribute data can return detailed error codes
that report the exact parameter that was wrong, we don't
need this much detail so we convert a parameter error into a
more general bad data status */
return( cryptArgError( status ) ? CRYPT_ERROR_BADDATA : status );
/* Move on to the next field */
continueDecoding:
attributeContinues = ( attributeInfoPtr->flags & FL_MORE ) ? TRUE : FALSE;
attributeInfoPtr++;
/* If this is the end of the attribute encoding info but we're
inside a SET OF and there's more attribute data present, go
back to the restart point and try again */
if( !attributeContinues && setofInfoPtr->endPos > 0 && \
stell( stream ) < setofInfoPtr->endPos )
{
assert( setofInfoPtr->restartPoint || \
setofInfoPtr->infoStart[ 1 ].fieldType == FIELDTYPE_IDENTIFIER );
attributeInfoPtr = setofInfoPtr->infoStart + 1;
attributeContinues = TRUE;
}
}
while( ( attributeContinues || setofStackPos > 1 ) && \
stell( stream ) < endPos );
/* Handle the special case of (a) the encoded data ending but fields with
default values being present, or (b) the encoded data continuing but
no more decoding information being present */
if( attributeContinues )
{
/* If there are default fields to follow, add the default value - see
the comment on the handling of default fields above. For now we
only add the first field since the only attributes where this
case can occur have a single default value as the next possible
entry, burrowing down further causes complications due to default
values present in optional sequences. As usual, we don't set any
specific error information for the default fields */
if( attributeInfoPtr->flags & FL_DEFAULT )
{
const int value = ( int ) attributeInfoPtr->defaultValue;
status = addAttributeField( attributeListPtrPtr,
attributeInfoPtr->fieldID, CRYPT_ATTRIBUTE_NONE,
&value, CRYPT_UNUSED, flags, NULL, NULL );
if( cryptStatusError( status ) )
return( status );
}
}
else
/* Some attributes have a SEQUENCE OF fields of no great use (e.g.
Microsoft's extensive crlDistributionPoints lists providing
redundant pointers to the same inaccessible site-internal
servers, although these are already handled above), if there's
any extraneous data left we just skip it */
while( stell( stream ) < endPos && cryptStatusOK( status ) && \
peekTag( stream ) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -