📄 certexrw.c
字号:
continue;
}
/* It's a correctly-encoded authorityKeyIdentifier, read it
normally */
sClearError( stream );
sseek( stream, offset );
}
/* If it's a known attribute, parse the payload */
if( attributeInfoPtr != NULL )
{
status = readAttribute( stream, attributeListPtrPtr,
attributeInfoPtr, attributeLength,
criticalFlag, errorLocus, errorType );
if( cryptStatusError( status ) )
return( status );
continue;
}
/* If it's a zero-length unrecognised attribute, don't add anything.
A zero length indicates that the attribute contains all default
values, however since we don't recognise the attribute we can't
fill these in so the attribute is in effect not present */
if( attributeLength <= 0 )
continue;
/* It's an unrecognised attribute type, add the raw data to the list
of attributes */
status = addAttribute( attributeType, attributeListPtrPtr, oid,
criticalFlag, sMemBufPtr( stream ),
attributeLength );
if( cryptStatusError( status ) )
{
if( status == CRYPT_ERROR_INITED )
{
/* If there's a duplicate attribute present, set error
information for it and flag it as a bad data error. We
can't set an error locus since it's an unknown blob */
*errorLocus = CRYPT_ATTRIBUTE_NONE;
*errorType = CRYPT_ERRTYPE_ATTR_PRESENT;
status = CRYPT_ERROR_BADDATA;
}
return( status );
}
sSkip( stream, attributeLength ); /* Skip the attribute data */
}
return( sGetStatus( stream ) );
}
/****************************************************************************
* *
* Attribute Write Routines *
* *
****************************************************************************/
/* When we write the attributes as a SET OF Attribute (as CMS does), we have
to sort them by encoded value. This is an incredible nuisance since it
requires that each value be encoded and stored in encoded form, then the
encoded forms sorted and emitted in that order. To avoid this hassle, we
keep a record of the current lowest encoded form and then find the next
one by encoding enough information (the SEQUENCE and OID, CMS attributes
don't have critical flags) on the fly to distinguish them. This is
actually less overhead than storing the encoded form because there are
only a small total number of attributes (usually 3) and we don't have to
malloc() storage for each one and manage the stored form if we do things
on the fly */
static ATTRIBUTE_LIST *getNextEncodedAttribute( ATTRIBUTE_LIST *attributeListPtr,
BYTE *prevEncodedForm )
{
ATTRIBUTE_LIST *currentAttributeListPtr = NULL;
STREAM stream;
BYTE currentEncodedForm[ 64 ], buffer[ 64 ];
/* Connect the output stream and give the current encoded form the
maximum possible value */
sMemOpen( &stream, buffer, 64 );
currentEncodedForm[ 0 ] = 0xFF;
/* Write the known attributes until we reach either the end of the list
or the first blob-type attribute */
while( attributeListPtr != NULL && !isBlobAttribute( attributeListPtr ) )
{
const BOOLEAN isConstructed = ( attributeListPtr->fifoEnd ) ? TRUE : FALSE;
const ATTRIBUTE_INFO *attributeInfoPtr = ( isConstructed ) ? \
attributeListPtr->encodingFifo[ attributeListPtr->fifoEnd - 1 ] :
attributeListPtr->attributeInfoPtr;
CRYPT_ATTRIBUTE_TYPE attributeID = attributeListPtr->attributeID;
int attributeDataSize;
/* Determine the size of the attribute payload */
if( isConstructed && attributeInfoPtr->fieldType != FIELDTYPE_CHOICE )
attributeDataSize = ( int ) sizeofObject( \
attributeListPtr->sizeFifo[ attributeListPtr->fifoEnd - 1 ] );
else
attributeDataSize = attributeListPtr->encodedSize;
/* Write the header and OID */
sseek( &stream, 0 );
writeSequence( &stream, sizeofOID( attributeInfoPtr->oid ) +
( int ) sizeofObject( attributeDataSize ) );
swrite( &stream, attributeInfoPtr->oid,
sizeofOID( attributeInfoPtr->oid ) );
/* Check to see whether this is larger than the previous value but
smaller than any other one we've seen. If it is, remember it */
if( memcmp( prevEncodedForm, buffer, 64 ) < 0 && \
memcmp( buffer, currentEncodedForm, 64 ) < 0 )
{
memcpy( currentEncodedForm, buffer, 64 );
currentAttributeListPtr = attributeListPtr;
}
/* Move on to the next attribute */
while( attributeListPtr != NULL && \
attributeListPtr->attributeID == attributeID )
attributeListPtr = attributeListPtr->next;
}
/* Write the blob-type attributes */
while( attributeListPtr != NULL )
{
/* Write the header and OID */
sseek( &stream, 0 );
writeSequence( &stream, sizeofOID( attributeListPtr->oid ) +
( int ) sizeofObject( attributeListPtr->dataLength ) );
swrite( &stream, attributeListPtr->oid,
sizeofOID( attributeListPtr->oid ) );
/* Check to see whether this is larger than the previous value but
smaller than any other one we've seen. If it is, remember it */
if( memcmp( prevEncodedForm, buffer, 64 ) < 0 && \
memcmp( buffer, currentEncodedForm, 64 ) < 0 )
{
memcpy( currentEncodedForm, buffer, 64 );
currentAttributeListPtr = attributeListPtr;
}
}
sMemDisconnect( &stream );
/* Remember the encoded form of the attribute and return a pointer to
it */
memcpy( prevEncodedForm, currentEncodedForm, 64 );
return( currentAttributeListPtr );
}
/* Determine the size of a set of attributes and validate and preprocess the
attribute information */
int sizeofAttributes( const ATTRIBUTE_LIST *attributeListPtr )
{
int encodeCritical, signUnrecognised, attributeSize = 0;
/* If there's nothing to write, return now */
if( attributeListPtr == NULL )
return( 0 );
assert( isReadPtr( attributeListPtr, ATTRIBUTE_LIST ) );
/* Determine the size of the recognised attributes */
krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,
RESOURCE_IMESSAGE_GETATTRIBUTE, &encodeCritical,
CRYPT_OPTION_CERT_ENCODE_CRITICAL );
while( attributeListPtr != NULL && !isBlobAttribute( attributeListPtr ) )
{
const BOOLEAN isConstructed = ( attributeListPtr->fifoEnd ) ? TRUE : FALSE;
const ATTRIBUTE_INFO *attributeInfoPtr = ( isConstructed ) ? \
attributeListPtr->encodingFifo[ attributeListPtr->fifoEnd - 1 ] :
attributeListPtr->attributeInfoPtr;
const CRYPT_ATTRIBUTE_TYPE attributeID = attributeListPtr->attributeID;
int length = sizeofOID( attributeInfoPtr->oid );
/* Determine the size of this attribute */
if( encodeCritical && ( attributeInfoPtr->flags & FL_CRITICAL ) )
length += sizeofBoolean();
if( isConstructed && attributeInfoPtr->fieldType != FIELDTYPE_CHOICE )
length += ( int ) sizeofObject( \
attributeListPtr->sizeFifo[ attributeListPtr->fifoEnd - 1 ] );
else
length += attributeListPtr->encodedSize;
attributeSize += ( int ) sizeofObject( sizeofObject( length ) );
/* Skip everything else in the current attribute */
while( attributeListPtr != NULL && \
attributeListPtr->attributeID == attributeID )
attributeListPtr = attributeListPtr->next;
}
/* If we're not going to be signing the blob-type attributes, return */
krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,
RESOURCE_IMESSAGE_GETATTRIBUTE, &signUnrecognised,
CRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES );
if( !signUnrecognised )
return( attributeSize );
/* Determine the size of the blob-type attributes */
while( attributeListPtr != NULL )
{
attributeSize += \
( int ) sizeofObject( sizeofOID( attributeListPtr->oid ) + \
( int ) sizeofObject( attributeListPtr->dataLength ) );
if( encodeCritical && \
( attributeListPtr->flags & ATTR_FLAG_CRITICAL ) )
attributeSize += sizeofBoolean();
attributeListPtr = attributeListPtr->next;
}
return( attributeSize );
}
/* Write an attribute field */
int writeAttributeField( STREAM *stream, ATTRIBUTE_LIST *attributeListPtr )
{
const BOOLEAN isSpecial = ( attributeListPtr->fifoPos ) ? TRUE : FALSE;
const ATTRIBUTE_INFO *attributeInfoPtr = ( isSpecial ) ? \
attributeListPtr->encodingFifo[ --attributeListPtr->fifoPos ] :
attributeListPtr->attributeInfoPtr;
const void *dataPtr = ( attributeListPtr->dataLength <= CRYPT_MAX_TEXTSIZE ) ? \
attributeListPtr->smallData : attributeListPtr->data;
int tag, size, payloadSize, fieldType = attributeInfoPtr->fieldType;
assert( isWritePtr( attributeListPtr, ATTRIBUTE_LIST ) );
/* If this is just a marker for a series of CHOICE alternatives, return
without doing anything */
if( fieldType == FIELDTYPE_CHOICE )
return( CRYPT_OK );
/* If this is a special-case object, determine the size of the data
payload */
if( isSpecial )
payloadSize = attributeListPtr->sizeFifo[ attributeListPtr->fifoPos ];
/* Calculate the size of the encoded data */
if( isSpecial )
{
/* If it's a special-case field, the data size is taken from
somewhere other than the user-supplied data */
switch( fieldType )
{
case FIELDTYPE_BLOB:
/* Fixed-value blob (as opposed to user-supplied one) */
size = ( int ) attributeInfoPtr->defaultValue;
break;
case FIELDTYPE_IDENTIFIER:
size = sizeofOID( attributeInfoPtr->oid );
break;
case BER_INTEGER:
size = sizeofShortInteger( attributeInfoPtr->defaultValue );
break;
case BER_SEQUENCE:
case BER_SET:
size = ( int ) sizeofObject( payloadSize );
break;
default:
assert( NOTREACHED );
return( CRYPT_ERROR );
}
}
else
/* It's a standard object, take the size from the user-supplied data */
switch( fieldType )
{
case FIELDTYPE_BLOB:
case BER_OBJECT_IDENTIFIER:
size = attributeListPtr->dataLength;
break;
case FIELDTYPE_DN:
size = sizeofDN( attributeListPtr->data );
break;
case FIELDTYPE_IDENTIFIER:
size = sizeofOID( attributeInfoPtr->oid );
break;
case BER_BITSTRING:
size = sizeofBitString( attributeListPtr->value );
break;
case BER_BOOLEAN:
size = sizeofBoolean();
break;
case BER_ENUMERATED:
size = sizeofEnumerated( attributeListPtr->value );
break;
case BER_INTEGER:
size = sizeofShortInteger( attributeListPtr->value );
break;
case BER_NULL:
/* This is stored as a pseudo-numeric value CRYPT_UNUSED so
we can't fall through to the default handler below */
size = sizeofNull();
break;
case BER_OCTETSTRING:
/* If it's an integer equivalent to an OCTET STRING hole, we
need to make sure we encode it correctly if the high bit
is set */
if( attributeInfoPtr->fieldEncodedType == BER_INTEGER )
size = sizeofInteger( dataPtr,
attributeListPtr->dataLength );
else
size = ( int ) sizeofObject( attributeListPtr->dataLength );
break;
case BER_TIME_GENERALIZED:
size = sizeofGeneralizedTime();
break;
case BER_TIME_UTC:
size = sizeofUTCTime();
break;
default:
size = ( int ) sizeofObject( attributeListPtr->dataLength );
}
/* If we're just calculating the attribute size, don't write any data */
if( stream == NULL )
return( ( attributeInfoPtr->flags & FL_EXPLICIT ) ? \
( int ) sizeofObject( size ) : size );
/* If the field is explicitly tagged, add another layer of wrapping */
if( attributeInfoPtr->flags & FL_EXPLICIT )
{
writeCtag( stream, attributeInfoPtr->fieldEncodedType );
writeLength( stream, size );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -