📄 certexrw.c
字号:
/* If the encoded field type differs from the actual field type (because
if implicit tagging), and we're not specifically using explicit
tagging, and it's not a DN in a GeneralName (which is a tagged IMPLICIT
SEQUENCE overridden to make it EXPLICIT because of the tagged CHOICE
encoding rules), set the tag to the encoded field type rather than the
actual field type */
if( attributeInfoPtr->fieldEncodedType && \
!( attributeInfoPtr->flags & FL_EXPLICIT ) && \
attributeInfoPtr->fieldType != FIELDTYPE_DN )
tag = attributeInfoPtr->fieldEncodedType;
else
tag = DEFAULT_TAG;
/* Write the data as appropriate */
if( isSpecial )
{
/* If it's a special-case field, the data is taken from somewhere
other than the user-supplied data */
switch( fieldType )
{
case FIELDTYPE_BLOB:
/* Fixed-value blob (as opposed to user-supplied one) */
return( swrite( stream, attributeInfoPtr->extraData, size ) );
case FIELDTYPE_IDENTIFIER:
return( swrite( stream, attributeInfoPtr->oid, size ) );
case BER_INTEGER:
return( writeShortInteger( stream, attributeInfoPtr->defaultValue,
tag ) );
case BER_SEQUENCE:
case BER_SET:
if( tag != DEFAULT_TAG )
{
/* If it's an implicitly tagged sequence, it's a
constructed object */
writeTag( stream, tag | BER_CONSTRUCTED );
writeLength( stream, payloadSize );
return( CRYPT_OK );
}
if( fieldType == BER_SET )
return( writeSet( stream, payloadSize ) );
return( writeSequence( stream, payloadSize ) );
}
assert( NOTREACHED );
return( CRYPT_ERROR );
}
/* It's a standard object, take the data from the user-supplied data */
switch( fieldType )
{
case FIELDTYPE_BLOB:
return( swrite( stream, dataPtr, attributeListPtr->dataLength ) );
case FIELDTYPE_DN:
return( writeDN( stream, attributeListPtr->data, tag ) );
case FIELDTYPE_IDENTIFIER:
return( swrite( stream, attributeInfoPtr->oid, size ) );
case BER_BITSTRING:
return( writeBitString( stream, ( int ) attributeListPtr->value, tag ) );
case BER_BOOLEAN:
return( writeBoolean( stream, ( BOOLEAN ) attributeListPtr->value, tag ) );
case BER_ENUMERATED:
return( writeEnumerated( stream, ( int ) attributeListPtr->value, tag ) );
case BER_INTEGER:
return( writeShortInteger( stream, attributeListPtr->value, tag ) );
case BER_NULL:
return( writeNull( stream, tag ) );
case BER_OBJECT_IDENTIFIER:
if( tag != DEFAULT_TAG )
{
/* This gets a bit messy because the OID is stored in
encoded form in the attribute, to write it as a tagged
value we have to write a different first byte */
sputc( stream, tag );
return( swrite( stream, ( ( BYTE * ) dataPtr ) + 1,
attributeListPtr->dataLength - 1 ) );
}
return( swrite( stream, dataPtr, attributeListPtr->dataLength ) );
case BER_OCTETSTRING:
/* If it's an integer equivalent to an OCTET STRING hole, we
need to use the INTEGER encoding rules rather than the
OCTET STRING ones */
if( attributeInfoPtr->fieldEncodedType == BER_INTEGER )
return( writeInteger( stream, dataPtr,
attributeListPtr->dataLength, DEFAULT_TAG ) );
return( writeOctetString( stream, dataPtr,
attributeListPtr->dataLength, tag ) );
case BER_STRING_IA5:
case BER_STRING_ISO646:
case BER_STRING_NUMERIC:
case BER_STRING_PRINTABLE:
return( writeCharacterString( stream, dataPtr, attributeListPtr->dataLength,
( tag == DEFAULT_TAG ) ? fieldType : tag ) );
case BER_TIME_GENERALIZED:
return( writeGeneralizedTime( stream, *( time_t * ) dataPtr, tag ) );
case BER_TIME_UTC:
return( writeUTCTime( stream, *( time_t * ) dataPtr, tag ) );
}
assert( NOTREACHED );
return( CRYPT_ERROR ); /* Get rid of compiler warning */
}
/* Write an attribute */
static int writeAttribute( STREAM *stream,
ATTRIBUTE_LIST **attributeListPtrPtr,
const int wrapperTag,
const BOOLEAN encodeCritical )
{
ATTRIBUTE_LIST *attributeListPtr = *attributeListPtrPtr;
int flagSize, status;
assert( isWritePtr( attributeListPtrPtr, ATTRIBUTE_LIST * ) && \
isReadPtr( *attributeListPtrPtr, ATTRIBUTE_LIST ) );
/* If it's a non-blob attribute, write it field by field */
if( !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 dataLength, length = sizeofOID( attributeInfoPtr->oid );
assert( isReadPtr( attributeInfoPtr, ATTRIBUTE_INFO ) );
/* Determine the size of the attribute payload */
flagSize = ( encodeCritical && ( attributeInfoPtr->flags & FL_CRITICAL ) ) ? \
sizeofBoolean() : 0;
if( isConstructed && attributeInfoPtr->fieldType != FIELDTYPE_CHOICE )
dataLength = ( int ) sizeofObject( \
attributeListPtr->sizeFifo[ attributeListPtr->fifoEnd - 1 ] );
else
dataLength = attributeListPtr->encodedSize;
/* Write the outer SEQUENCE, OID, critical flag (if it's set) and
appropriate wrapper for the attribute payload */
writeSequence( stream, length + flagSize + \
( int ) sizeofObject( dataLength ) );
swrite( stream, attributeInfoPtr->oid,
sizeofOID( attributeInfoPtr->oid ) );
if( flagSize )
writeBoolean( stream, TRUE, DEFAULT_TAG );
status = writeTag( stream, wrapperTag );
writeLength( stream, dataLength );
/* Write the current attribute */
while( attributeListPtr != NULL && \
attributeListPtr->attributeID == attributeID )
{
/* Write any encapsulating SEQUENCE's if necessary, followed by
the field itself. In some rare instances we may have a zero-
length SEQUENCE (if all the member(s) of the sequence have
default values), so we only try to write the member if there's
encoding information for it present */
attributeListPtr->fifoPos = attributeListPtr->fifoEnd;
while( cryptStatusOK( status ) && attributeListPtr->fifoPos )
status = writeAttributeField( stream,
( ATTRIBUTE_LIST * ) attributeListPtr );
if( cryptStatusOK( status ) && \
attributeListPtr->attributeInfoPtr != NULL )
status = writeAttributeField( stream,
( ATTRIBUTE_LIST * ) attributeListPtr );
if( cryptStatusError( status ) )
return( status );
/* Move on to the next attribute field */
attributeListPtr = attributeListPtr->next;
}
*attributeListPtrPtr = attributeListPtr;
return( CRYPT_OK );
}
/* Write the header, OID, critical flag (if present), and payload wrapped
up as appropriate */
flagSize = ( encodeCritical && \
( attributeListPtr->flags & ATTR_FLAG_CRITICAL ) ) ? \
sizeofBoolean() : 0;
writeSequence( stream, sizeofOID( attributeListPtr->oid ) + flagSize +
( int ) sizeofObject( attributeListPtr->dataLength ) );
swrite( stream, attributeListPtr->oid,
sizeofOID( attributeListPtr->oid ) );
if( flagSize )
writeBoolean( stream, TRUE, DEFAULT_TAG );
writeTag( stream, wrapperTag );
writeLength( stream, attributeListPtr->dataLength );
status = swrite( stream,
( attributeListPtr->dataLength <= CRYPT_MAX_TEXTSIZE ) ? \
attributeListPtr->smallData : attributeListPtr->data,
attributeListPtr->dataLength );
if( cryptStatusError( status ) )
return( status );
*attributeListPtrPtr = attributeListPtr->next;
return( CRYPT_OK );
}
/* Write a set of attributes */
int writeAttributes( STREAM *stream, ATTRIBUTE_LIST *attributeListPtr,
const CRYPT_CERTTYPE_TYPE type, const int attributeSize )
{
const int wrapperTag = ( type == CRYPT_CERTTYPE_CMS_ATTRIBUTES ) ? \
BER_SET : BER_OCTETSTRING;
int encodeCritical, signUnrecognised, status = CRYPT_OK;
/* If there's nothing to write, return now */
if( attributeSize == 0 )
return( CRYPT_OK );
assert( isWritePtr( attributeListPtr, ATTRIBUTE_LIST ) );
krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,
RESOURCE_IMESSAGE_GETATTRIBUTE, &encodeCritical,
CRYPT_OPTION_CERT_ENCODE_CRITICAL );
/* CMS attributes work somewhat differently from normal attributes in
that, since they're encoded as a SET OF Attribute, they have to be
sorted according to their encoded form before being written. For
this reason we don't write them sorted by OID as with the other
attributes, but keep writing the next-lowest attribute until they've
all been written */
if( type == CRYPT_CERTTYPE_CMS_ATTRIBUTES )
{
ATTRIBUTE_LIST *currentAttributePtr;
BYTE currentEncodedForm[ 64 ];
writeCtag( stream, CTAG_SI_AUTHENTICATEDATTRIBUTES );
writeLength( stream, attributeSize );
memset( currentEncodedForm, 0, 64 ); /* Set lowest encoded form */
currentAttributePtr = getNextEncodedAttribute( attributeListPtr,
currentEncodedForm );
do
{
status = writeAttribute( stream, ¤tAttributePtr, wrapperTag,
encodeCritical );
currentAttributePtr = getNextEncodedAttribute( attributeListPtr,
currentEncodedForm );
}
while( currentAttributePtr != NULL && cryptStatusOK( status ) );
return( status );
}
/* Write the appropriate extensions tag for the certificate object and
determine how far we can read. CRLs and OCSP requests/responses have
two extension types, per-entry extensions and entire-CRL/request
extensions which have different tagging. To differentiate between
the two, we write per-entry extensions with a type of
CRYPT_CERTTYPE_NONE */
switch( type )
{
case CRYPT_CERTTYPE_CERTIFICATE:
case CRYPT_CERTTYPE_CRL:
writeCtag( stream, ( type == CRYPT_CERTTYPE_CERTIFICATE ) ? \
CTAG_CE_EXTENSIONS : CTAG_CR_EXTENSIONS );
writeLength( stream, ( int ) sizeofObject( attributeSize ) );
writeSequence( stream, attributeSize );
break;
case CRYPT_CERTTYPE_CERTREQUEST:
writeSequence( stream, sizeofOID( OID_PKCS9_EXTREQ ) + \
( int ) sizeofObject( sizeofObject( attributeSize ) ) );
swrite( stream, OID_PKCS9_EXTREQ, sizeofOID( OID_PKCS9_EXTREQ ) );
writeSet( stream, ( int ) sizeofObject( attributeSize ) );
writeSequence( stream, attributeSize );
break;
case CRYPT_CERTTYPE_REQUEST_CERT:
case CRYPT_CERTTYPE_REQUEST_REVOCATION:
/* No wrapper, extensions are written directly */
break;
case CRYPT_CERTTYPE_ATTRIBUTE_CERT:
case CRYPT_CERTTYPE_PKIUSER:
case CRYPT_CERTTYPE_NONE:
writeSequence( stream, attributeSize );
break;
case CRYPT_CERTTYPE_OCSP_REQUEST:
writeConstructed( stream, ( int ) sizeofObject( attributeSize ),
CTAG_OR_EXTENSIONS );
writeSequence( stream, attributeSize );
break;
case CRYPT_CERTTYPE_OCSP_RESPONSE:
writeConstructed( stream, ( int ) sizeofObject( attributeSize ),
CTAG_OP_EXTENSIONS );
writeSequence( stream, attributeSize );
break;
default:
assert( NOTREACHED );
return( CRYPT_ERROR );
}
/* Write the known attributes until we reach either the end of the list
or the first blob-type attribute */
while( attributeListPtr != NULL && \
!isBlobAttribute( attributeListPtr ) && cryptStatusOK( status ) )
status = writeAttribute( stream, &attributeListPtr, wrapperTag,
encodeCritical );
/* 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( status );
/* Write the blob-type attributes */
while( attributeListPtr != NULL && cryptStatusOK( status ) )
status = writeAttribute( stream, &attributeListPtr, wrapperTag,
encodeCritical );
return( status );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -