📄 asn1_algid.c
字号:
#ifdef USE_RC5
case CRYPT_ALGO_RC5:
paramSize = sizeofShortInteger( 16 ) + \
sizeofShortInteger( 12 ) + \
sizeofShortInteger( 64 ) + \
sizeofIV;
writeSequence( stream, oidSize + \
( int ) sizeofObject( paramSize ) );
swrite( stream, oid, oidSize );
writeSequence( stream, paramSize );
writeShortInteger( stream, 16, DEFAULT_TAG ); /* Version */
writeShortInteger( stream, 12, DEFAULT_TAG ); /* Rounds */
writeShortInteger( stream, 64, DEFAULT_TAG ); /* Block size */
return( writeOctetString( stream, iv, ivSize, DEFAULT_TAG ) );
#endif /* USE_RC5 */
#ifdef USE_SKIPJACK
case CRYPT_ALGO_SKIPJACK:
writeSequence( stream, oidSize + \
( int ) sizeofObject( sizeofIV ) );
swrite( stream, oid, oidSize );
writeSequence( stream, sizeofIV );
return( writeOctetString( stream, iv, ivSize, DEFAULT_TAG ) );
#endif /* USE_SKIPJACK */
}
retIntError();
}
/****************************************************************************
* *
* AlgorithmIdentifier Routines *
* *
****************************************************************************/
/* Because AlgorithmIdentifiers are only defined for a subset of the
algorithms that cryptlib supports we have to check that the algorithm
and mode being used can be represented in encoded data before we try to
do anything with it */
CHECK_RETVAL_BOOL \
BOOLEAN checkAlgoID( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,
IN_MODE const CRYPT_MODE_TYPE cryptMode )
{
REQUIRES_B( cryptAlgo > CRYPT_ALGO_NONE && cryptAlgo < CRYPT_ALGO_LAST );
REQUIRES_B( cryptMode >= CRYPT_MODE_NONE && cryptMode < CRYPT_MODE_LAST );
return( ( algorithmToOIDcheck( cryptAlgo, cryptMode ) != NULL ) ? \
TRUE : FALSE );
}
/* Determine the size of an AlgorithmIdentifier record */
CHECK_RETVAL \
int sizeofAlgoIDex( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,
IN_RANGE( 0, 999 ) const int parameter,
IN_LENGTH_SHORT_Z const int extraLength )
{
const BYTE *oid = algorithmToOID( cryptAlgo, parameter );
REQUIRES( cryptAlgo > CRYPT_ALGO_NONE && cryptAlgo < CRYPT_ALGO_LAST );
REQUIRES( parameter >= 0 && parameter <= 999 );
REQUIRES( extraLength >= 0 && extraLength < MAX_INTLENGTH_SHORT );
REQUIRES( oid != NULL );
return( ( int ) sizeofObject( sizeofOID( oid ) + \
( ( extraLength > 0 ) ? extraLength : \
sizeofNull() ) ) );
}
CHECK_RETVAL \
int sizeofAlgoID( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo )
{
REQUIRES( cryptAlgo > CRYPT_ALGO_NONE && cryptAlgo < CRYPT_ALGO_LAST );
return( sizeofAlgoIDex( cryptAlgo, CRYPT_ALGO_NONE, 0 ) );
}
/* Write an AlgorithmIdentifier record */
RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int writeAlgoIDex( INOUT STREAM *stream,
IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,
IN_RANGE( 0, 999 ) const int parameter,
IN_LENGTH_SHORT_Z const int extraLength )
{
const BYTE *oid = algorithmToOID( cryptAlgo, parameter );
int status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
REQUIRES_S( cryptAlgo > CRYPT_ALGO_NONE && cryptAlgo < CRYPT_ALGO_LAST );
REQUIRES_S( parameter >= 0 && parameter <= 999 );
REQUIRES_S( extraLength >= 0 && extraLength < MAX_INTLENGTH_SHORT );
REQUIRES_S( oid != NULL );
/* Write the AlgorithmIdentifier field */
writeSequence( stream, sizeofOID( oid ) + \
( ( extraLength > 0 ) ? extraLength : sizeofNull() ) );
status = swrite( stream, oid, sizeofOID( oid ) );
if( extraLength > 0 )
{
/* Parameters will be written by the caller */
return( status );
}
/* No extra parameters so we need to write a NULL */
return( writeNull( stream, DEFAULT_TAG ) );
}
RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int writeAlgoID( INOUT STREAM *stream,
IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
REQUIRES_S( cryptAlgo > CRYPT_ALGO_NONE && cryptAlgo < CRYPT_ALGO_LAST );
return( writeAlgoIDex( stream, cryptAlgo, CRYPT_ALGO_NONE, 0 ) );
}
/* Read an AlgorithmIdentifier record. There are three versions of
this:
readAlgoID: Reads an algorithm, assumes that there are no secondary
algorithm or mode and algorithm parameters present and returns an
error if there are.
readAlgoIDext: Reads an algorithm and secondary algorithm or mode,
assumes that there are no algorithm parameters present and returns
an error if there are.
readAlgoIDparams: Reads an algorithm and the length of the extra
information */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int readAlgoID( INOUT STREAM *stream,
OUT_ALGO_Z CRYPT_ALGO_TYPE *cryptAlgo )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( cryptAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );
return( readAlgoIDheader( stream, cryptAlgo, NULL, NULL, DEFAULT_TAG ) );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
int readAlgoIDext( INOUT STREAM *stream,
OUT_ALGO_Z CRYPT_ALGO_TYPE *cryptAlgo,
OUT_ALGO_Z CRYPT_ALGO_TYPE *altCryptAlgo )
{
int altAlgo, status; /* 'altAlgo' must be type integer */
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( cryptAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );
assert( isWritePtr( altCryptAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );
/* Clear return value (the others are cleared by readAlgoIDheader()) */
*altCryptAlgo = CRYPT_ALGO_NONE;
status = readAlgoIDheader( stream, cryptAlgo, &altAlgo, NULL,
DEFAULT_TAG );
if( cryptStatusOK( status ) )
*altCryptAlgo = altAlgo; /* CRYPT_MODE_TYPE vs. integer */
return( status );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
int readAlgoIDparams( INOUT STREAM *stream,
OUT_ALGO_Z CRYPT_ALGO_TYPE *cryptAlgo,
OUT_LENGTH_SHORT_Z int *extraLength )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( cryptAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );
assert( isWritePtr( extraLength, sizeof( int ) ) );
return( readAlgoIDheader( stream, cryptAlgo, NULL, extraLength,
DEFAULT_TAG ) );
}
/* Determine the size of an AlgorithmIdentifier record from a context */
CHECK_RETVAL \
int sizeofContextAlgoID( IN_HANDLE const CRYPT_CONTEXT iCryptContext,
IN_RANGE( 0, 999 ) const int parameter )
{
CRYPT_ALGO_TYPE cryptAlgo;
int status;
REQUIRES( isHandleRangeValid( iCryptContext ) );
REQUIRES( parameter >= 0 && parameter <= 999 );
/* Write the algoID only */
status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,
&cryptAlgo, CRYPT_CTXINFO_ALGO );
if( cryptStatusError( status ) )
return( status );
return( sizeofAlgoIDex( cryptAlgo, parameter, 0 ) );
}
/* Write an AlgorithmIdentifier record from a context */
RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int writeContextAlgoID( INOUT STREAM *stream,
IN_HANDLE const CRYPT_CONTEXT iCryptContext,
IN_RANGE( 0, 999 ) const int parameter )
{
CRYPT_ALGO_TYPE cryptAlgo;
int status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
REQUIRES_S( isHandleRangeValid( iCryptContext ) );
REQUIRES_S( parameter >= 0 && parameter <= 999 );
status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,
&cryptAlgo, CRYPT_CTXINFO_ALGO );
if( cryptStatusError( status ) )
return( status );
return( writeAlgoIDex( stream, cryptAlgo, parameter, 0 ) );
}
/* Turn an AlgorithmIdentifier into a context */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int readContextAlgoID( INOUT STREAM *stream,
OUT_OPT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,
INOUT_OPT QUERY_INFO *queryInfo,
IN_TAG const int tag )
{
QUERY_INFO localQueryInfo, *queryInfoPtr = queryInfo;
MESSAGE_CREATEOBJECT_INFO createInfo;
int status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( iCryptContext == NULL || \
isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );
assert( queryInfo == NULL || \
isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
REQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );
/* Clear return value */
if( iCryptContext != NULL )
*iCryptContext = CRYPT_ERROR;
/* If the user isn't interested in the algorithm details, use a local
query structure to contain them */
if( queryInfo == NULL )
{
memset( &localQueryInfo, 0, sizeof( localQueryInfo ) );
queryInfoPtr = &localQueryInfo;
}
/* Read the algorithm info. If we're not creating a context from the
info, we're done */
status = readAlgoIDInfo( stream, queryInfoPtr, tag );
if( cryptStatusError( status ) || iCryptContext == NULL )
return( status );
/* Create the object from it */
setMessageCreateObjectInfo( &createInfo, queryInfoPtr->cryptAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
if( cryptStatusError( status ) )
return( status );
if( queryInfoPtr->cryptAlgo > CRYPT_ALGO_LAST_CONVENTIONAL )
{
/* If it's not a conventional encryption algorithm, we're done */
*iCryptContext = createInfo.cryptHandle;
return( CRYPT_OK );
}
ENSURES_S( queryInfoPtr->cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \
queryInfoPtr->cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL );
status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,
&queryInfoPtr->cryptMode, CRYPT_CTXINFO_MODE );
if( cryptStatusOK( status ) && \
!isStreamCipher( queryInfoPtr->cryptAlgo ) )
{
int ivLength;
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_GETATTRIBUTE, &ivLength,
CRYPT_CTXINFO_IVSIZE );
if( cryptStatusOK( status ) )
{
MESSAGE_DATA msgData;
setMessageData( &msgData, queryInfoPtr->iv,
min( ivLength, queryInfoPtr->ivLength ) );
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_IV );
}
}
if( cryptStatusError( status ) )
{
/* If there's an error in the parameters stored with the key we'll
get an arg or attribute error when we try to set the attribute so
we translate it into an error code which is appropriate for the
situation. In addition since this is (arguably) a stream format
error (the data read from the stream is invalid) we also set the
stream status */
krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
if( cryptArgError( status ) )
return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
return( status );
}
*iCryptContext = createInfo.cryptHandle;
return( CRYPT_OK );
}
/* Read/write a non-crypto algorithm identifier, used for things like
content types. This just wraps the given OID up in the
AlgorithmIdentifier and writes it */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int readGenericAlgoID( INOUT STREAM *stream,
IN_BUFFER( oidLength ) const BYTE *oid,
IN_LENGTH_OID const int oidLength )
{
int length, status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( oid, oidLength ) && \
oidLength == sizeofOID( oid ) );
REQUIRES_S( oidLength >= MIN_OID_SIZE && oidLength <= MAX_OID_SIZE );
/* Read the AlgorithmIdentifier wrapper and OID. One possible
complication here is the standard NULL vs.absent AlgorithmIdentifier
parameter issue, to handle this we allow either option */
status = readSequence( stream, &length );
if( cryptStatusOK( status ) )
status = readFixedOID( stream, oid, oidLength );
if( cryptStatusError( status ) )
return( status );
length -= oidLength;
if( length > 0 )
return( readNull( stream ) );
return( CRYPT_OK );
}
RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int writeGenericAlgoID( INOUT STREAM *stream,
IN_BUFFER( oidLength ) const BYTE *oid,
IN_LENGTH_OID const int oidLength )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( oid, oidLength ) && \
oidLength == sizeofOID( oid ) );
REQUIRES_S( oidLength >= MIN_OID_SIZE && oidLength <= MAX_OID_SIZE );
writeSequence( stream, oidLength );
return( writeOID( stream, oid ) );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -