asn1_ext.c
来自「cryptlib安全工具包」· C语言 代码 · 共 461 行 · 第 1/2 页
C
461 行
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int writeCMSheader( INOUT STREAM *stream,
IN_BUFFER( contentOIDlength ) const BYTE *contentOID,
IN_LENGTH_OID const int contentOIDlength,
IN_LENGTH_INDEF const long dataSize,
const BOOLEAN isInnerHeader )
{
BOOLEAN isOctetString = ( isInnerHeader || \
( contentOIDlength == 11 && \
!memcmp( contentOID, OID_CMS_DATA, 11 ) ) ) ? \
TRUE : FALSE;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( contentOID, contentOIDlength ) && \
contentOIDlength == sizeofOID( contentOID ) );
REQUIRES_S( contentOID[ 0 ] == BER_OBJECT_IDENTIFIER );
REQUIRES_S( contentOIDlength >= MIN_OID_SIZE && \
contentOIDlength <= MAX_OID_SIZE );
REQUIRES_S( dataSize == CRYPT_UNUSED || \
( dataSize >= 0 && dataSize < MAX_INTLENGTH ) );
/* May be zero for degenerate (detached) signatures */
/* The handling of the wrapper type for the content is rather complex.
If it's an outer header, it's an OCTET STRING for data and a SEQUENCE
for everything else. If it's an inner header it usually follows the
same rule, however for signed data the content was changed from
content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL
in PKCS #7 to
eContent [0] EXPLICIT OCTET STRING OPTIONAL
for CMS (it was always an OCTET STRING for encrypted data). To
complicate things, there are some older implementations based on the
original PKCS #7 interpretation that use a SEQUENCE (namely
AuthentiCode). To resolve this we use an OCTET STRING for inner
content unless the content type is spcIndirectDataContext */
if( isInnerHeader && contentOIDlength == 12 && \
!memcmp( contentOID, OID_MS_SPCINDIRECTDATACONTEXT, 12 ) )
isOctetString = FALSE;
/* If a size is given, write the definite form */
if( dataSize != CRYPT_UNUSED )
{
int status;
writeSequence( stream, contentOIDlength + ( ( dataSize > 0 ) ? \
( int ) sizeofObject( sizeofObject( dataSize ) ) : 0 ) );
status = writeOID( stream, contentOID );
if( dataSize <= 0 )
return( status ); /* No content, exit */
writeConstructed( stream, sizeofObject( dataSize ), 0 );
if( isOctetString )
return( writeOctetStringHole( stream, dataSize, DEFAULT_TAG ) );
return( writeSequence( stream, dataSize ) );
}
/* No size given, write the indefinite form */
writeSequenceIndef( stream );
writeOID( stream, contentOID );
writeCtag0Indef( stream );
return( isOctetString ? writeOctetStringIndef( stream ) : \
writeSequenceIndef( stream ) );
}
/* Read and write an encryptedContentInfo header. The inner content may be
implicitly or explicitly tagged depending on the exact content type */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int sizeofCMSencrHeader( IN_BUFFER( contentOIDlength ) const BYTE *contentOID,
IN_LENGTH_OID const int contentOIDlength,
IN_LENGTH_INDEF const long dataSize,
IN_HANDLE const CRYPT_CONTEXT iCryptContext )
{
STREAM nullStream;
int status, cryptInfoSize = DUMMY_INIT;
assert( isReadPtr( contentOID, contentOIDlength ) && \
contentOIDlength == sizeofOID( contentOID ) );
REQUIRES( contentOID[ 0 ] == BER_OBJECT_IDENTIFIER );
REQUIRES( contentOIDlength >= MIN_OID_SIZE && \
contentOIDlength <= MAX_OID_SIZE );
REQUIRES( dataSize == CRYPT_UNUSED || \
( dataSize > 0 && dataSize < MAX_INTLENGTH ) );
REQUIRES( isHandleRangeValid( iCryptContext ) );
/* Determine the encoded size of the AlgorithmIdentifier */
sMemNullOpen( &nullStream );
status = writeCryptContextAlgoID( &nullStream, iCryptContext );
if( cryptStatusOK( status ) )
cryptInfoSize = stell( &nullStream );
sMemClose( &nullStream );
if( cryptStatusError( status ) )
return( status );
/* Calculate the encoded size of the SEQUENCE + OID + AlgoID + [0] for
the definite or indefinite forms (the size 2 is for the tag + 0x80
indefinite-length indicator and the EOC octets at the end) */
if( dataSize != CRYPT_UNUSED )
{
return( ( int ) \
( sizeofObject( contentOIDlength + \
cryptInfoSize + \
sizeofObject( dataSize ) ) - dataSize ) );
}
return( 2 + contentOIDlength + cryptInfoSize + 2 );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int readCMSencrHeader( INOUT STREAM *stream,
IN_ARRAY( noOidInfoEntries ) const OID_INFO *oidInfo,
IN_RANGE( 1, 50 ) const int noOidInfoEntries,
OUT_OPT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,
INOUT_OPT QUERY_INFO *queryInfo )
{
QUERY_INFO localQueryInfo, *queryInfoPtr = ( queryInfo == NULL ) ? \
&localQueryInfo : queryInfo;
long length;
int selectionID, tag, status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( oidInfo, sizeof( OID_INFO ) * noOidInfoEntries ) );
assert( iCryptContext == NULL || \
isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );
assert( queryInfo == NULL || \
isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
REQUIRES_S( noOidInfoEntries > 0 && noOidInfoEntries <= 50 );
/* Clear return values */
if( iCryptContext != NULL )
*iCryptContext = CRYPT_ERROR;
memset( queryInfoPtr, 0, sizeof( QUERY_INFO ) );
/* Set up the basic query info fields. Since this isn't a proper key
exchange or signature object we can't properly set up all of the
fields like the type (it's not any CRYPT_OBJECT_TYPE) or version
fields */
queryInfoPtr->formatType = CRYPT_FORMAT_CMS;
/* Read the outer SEQUENCE, OID, and AlgorithmIdentifier. We can't use
a normal readSequence() here because the data length could be much
longer than the maximum allowed in the readSequence() sanity check */
readLongSequence( stream, NULL );
status = readOID( stream, oidInfo, noOidInfoEntries, &selectionID );
if( cryptStatusOK( status ) )
status = readContextAlgoID( stream, iCryptContext, queryInfoPtr,
DEFAULT_TAG );
if( cryptStatusError( status ) )
return( status );
/* Read the content [0] tag, which may be either primitive or constructed
depending on the content */
tag = peekTag( stream );
if( cryptStatusError( tag ) )
return( tag );
status = readLongGenericHole( stream, &length, tag );
if( cryptStatusOK( status ) && \
( tag != MAKE_CTAG( 0 ) && tag != MAKE_CTAG_PRIMITIVE( 0 ) ) )
{
sSetError( stream, CRYPT_ERROR_BADDATA );
status = CRYPT_ERROR_BADDATA;
}
if( cryptStatusError( status ) )
{
if( iCryptContext != NULL )
krnlSendNotifier( *iCryptContext, IMESSAGE_DECREFCOUNT );
return( status );
}
queryInfoPtr->size = length;
return( selectionID );
}
RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int writeCMSencrHeader( INOUT STREAM *stream,
IN_BUFFER( contentOIDlength ) const BYTE *contentOID,
IN_LENGTH_OID const int contentOIDlength,
IN_LENGTH_INDEF const long dataSize,
IN_HANDLE const CRYPT_CONTEXT iCryptContext )
{
STREAM nullStream;
int cryptInfoSize = DUMMY_INIT, status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( contentOID, contentOIDlength ) && \
contentOIDlength == sizeofOID( contentOID ) );
REQUIRES_S( contentOID[ 0 ] == BER_OBJECT_IDENTIFIER );
REQUIRES_S( contentOIDlength >= MIN_OID_SIZE && \
contentOIDlength <= MAX_OID_SIZE );
REQUIRES_S( dataSize == CRYPT_UNUSED || \
( dataSize > 0 && dataSize < MAX_INTLENGTH ) );
REQUIRES_S( isHandleRangeValid( iCryptContext ) );
/* Determine the encoded size of the AlgorithmIdentifier */
sMemNullOpen( &nullStream );
status = writeCryptContextAlgoID( &nullStream, iCryptContext );
if( cryptStatusOK( status ) )
cryptInfoSize = stell( &nullStream );
sMemClose( &nullStream );
if( cryptStatusError( status ) )
return( status );
/* If a size is given, write the definite form */
if( dataSize != CRYPT_UNUSED )
{
writeSequence( stream, contentOIDlength + cryptInfoSize + \
( int ) sizeofObject( dataSize ) );
writeOID( stream, contentOID );
status = writeCryptContextAlgoID( stream, iCryptContext );
if( cryptStatusError( status ) )
return( status );
return( writeOctetStringHole( stream, dataSize, 0 ) );
}
/* No size given, write the indefinite form */
writeSequenceIndef( stream );
writeOID( stream, contentOID );
status = writeCryptContextAlgoID( stream, iCryptContext );
if( cryptStatusError( status ) )
return( status );
return( writeCtag0Indef( stream ) );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?