📄 asn1oid.c
字号:
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_IV );
ivSize = msgData.length;
sizeofIV = ( int ) sizeofObject( ivSize );
}
if( cryptStatusError( status ) )
return( status );
if( ( oid = algorithmToOIDcheck( algorithm, ( CRYPT_ALGO ) mode ) ) == NULL )
/* Some algorithm+mode combinations can't be encoded using the
oddball collection of PKCS #7 OIDs, the best we can do is return
a CRYPT_ERROR_NOTAVAIL */
return( CRYPT_ERROR_NOTAVAIL );
oidSize = sizeofOID( oid );
/* Write algorithm-specific OID parameters */
if( algorithm == CRYPT_ALGO_CAST )
{
const int paramSize = sizeofIV + sizeofShortInteger( 128 );
writeSequence( stream, oidSize + ( int ) sizeofObject( paramSize ) );
swrite( stream, oid, oidSize );
writeSequence( stream, paramSize );
writeOctetString( stream, iv, ivSize, DEFAULT_TAG );
return( writeShortInteger( stream, 128, DEFAULT_TAG ) );
}
if( algorithm == CRYPT_ALGO_AES || algorithm == CRYPT_ALGO_DES || \
algorithm == CRYPT_ALGO_3DES || algorithm == CRYPT_ALGO_BLOWFISH )
{
const int noBits = ( algorithm == CRYPT_ALGO_AES ) ? 128 : 64;
const int paramSize = ( mode == CRYPT_MODE_ECB ) ? sizeofNull() : \
( ( mode == CRYPT_MODE_CBC ) || \
( algorithm == CRYPT_ALGO_AES && mode == CRYPT_MODE_OFB ) ) ? \
sizeofIV : \
( int ) sizeofObject( sizeofIV + sizeofShortInteger( noBits ) );
writeSequence( stream, oidSize + paramSize );
if( algorithm == CRYPT_ALGO_AES )
{
int keySize;
/* AES uses a bizarre encoding in which the last byte of the OID
jumps in steps of 20 depending on the key size, so we adjust
the OID we actually write based on the key size (it's
extremely unlikely that any implementation cares about this
since the size information is always communicated anderswhere,
but we do it just in case) */
krnlSendMessage( iCryptContext, RESOURCE_IMESSAGE_GETATTRIBUTE,
&keySize, CRYPT_CTXINFO_KEYSIZE );
swrite( stream, oid, oidSize - 1 );
sputc( stream, oid[ oidSize - 1 ] + \
( keySize == 16 ? 0 : keySize == 24 ? 20 : 40 ) );
}
else
swrite( stream, oid, oidSize );
if( mode == CRYPT_MODE_ECB )
return( writeNull( stream, DEFAULT_TAG ) );
if( ( mode == CRYPT_MODE_CBC ) || \
( algorithm == CRYPT_ALGO_AES && mode == CRYPT_MODE_OFB ) )
return( writeOctetString( stream, iv, ivSize, DEFAULT_TAG ) );
writeSequence( stream, sizeofIV + sizeofShortInteger( noBits ) );
writeOctetString( stream, iv, ivSize, DEFAULT_TAG );
return( writeShortInteger( stream, noBits, DEFAULT_TAG ) );
}
if( algorithm == CRYPT_ALGO_IDEA )
{
const int paramSize = ( mode == CRYPT_MODE_ECB ) ? \
sizeofNull() : ( int ) sizeofObject( sizeofIV );
writeSequence( stream, oidSize + paramSize );
swrite( stream, oid, oidSize );
if( mode == CRYPT_MODE_ECB )
return( writeNull( stream, DEFAULT_TAG ) );
writeSequence( stream, sizeofIV );
return( writeOctetString( stream, iv, ivSize, \
( mode == CRYPT_MODE_CFB ) ? \
MAKE_CTAG_PRIMITIVE( 3 ) : DEFAULT_TAG ) );
}
if( algorithm == CRYPT_ALGO_RC2 )
{
const int paramSize = ( ( mode == CRYPT_MODE_ECB ) ? 0 : sizeofIV ) +
sizeofShortInteger( RC2_KEYSIZE_MAGIC );
writeSequence( stream, oidSize + ( int ) sizeofObject( paramSize ) );
swrite( stream, oid, oidSize );
writeSequence( stream, paramSize );
status = writeShortInteger( stream, RC2_KEYSIZE_MAGIC, DEFAULT_TAG );
if( mode == CRYPT_MODE_CBC )
return( writeOctetString( stream, iv, ivSize, DEFAULT_TAG ) );
return( status );
}
if( algorithm == CRYPT_ALGO_RC4 )
{
writeSequence( stream, oidSize + sizeofNull() );
swrite( stream, oid, oidSize );
return( writeNull( stream, DEFAULT_TAG ) );
}
if( algorithm == CRYPT_ALGO_RC5 )
{
const int 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 ) );
}
if( algorithm == CRYPT_ALGO_SKIPJACK )
{
writeSequence( stream, oidSize + ( int ) sizeofObject( sizeofIV ) );
swrite( stream, oid, oidSize );
writeSequence( stream, sizeofIV );
return( writeOctetString( stream, iv, ivSize, DEFAULT_TAG ) );
}
assert( NOTREACHED );
return( CRYPT_ERROR ); /* Get rid of compiler warning */
}
/****************************************************************************
* *
* AlgorithmIdentifier Routines *
* *
****************************************************************************/
/* Because AlgorithmIdentifier's are only defined for a subset of the
algorithms which 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 */
BOOLEAN checkAlgoID( const CRYPT_ALGO algorithm, const CRYPT_MODE mode )
{
return( ( algorithmToOIDcheck( algorithm, \
( CRYPT_ALGO ) mode ) != NULL ) ? TRUE : FALSE );
}
/* Determine the size of an AlgorithmIdentifier record */
int sizeofAlgoIDex( const CRYPT_ALGO algorithm, const CRYPT_ALGO subAlgorithm,
const int extraLength )
{
return( ( int ) sizeofObject( \
sizeofOID( algorithmToOID( algorithm, subAlgorithm ) ) + \
( extraLength ? extraLength : sizeofNull() ) ) );
}
int sizeofAlgoID( const CRYPT_ALGO algorithm )
{
return( sizeofAlgoIDex( algorithm, CRYPT_ALGO_NONE, 0 ) );
}
/* Write an AlgorithmIdentifier record */
int writeAlgoIDex( STREAM *stream, const CRYPT_ALGO algorithm,
const CRYPT_ALGO subAlgorithm, const int extraLength )
{
BYTE *oid = algorithmToOID( algorithm, subAlgorithm );
const int oidSize = sizeofOID( oid );
/* Write the AlgorithmIdentifier field */
writeSequence( stream, oidSize + \
( extraLength ? extraLength : sizeofNull() ) );
swrite( stream, oid, oidSize );
if( !extraLength )
/* No extra parameters so we need to write a NULL */
writeNull( stream, DEFAULT_TAG );
return( sGetStatus( stream ) );
}
int writeAlgoID( STREAM *stream, const CRYPT_ALGO algorithm )
{
return( writeAlgoIDex( stream, algorithm, CRYPT_ALGO_NONE, 0 ) );
}
/* Read an AlgorithmIdentifier record */
int readAlgoIDex( STREAM *stream, CRYPT_ALGO *algorithm,
CRYPT_ALGO *subAlgorithm, int *extraLength )
{
CRYPT_ALGO cryptAlgo;
BYTE buffer[ MAX_OID_SIZE ];
int bufferLength, cryptSubAlgo, length, status;
/* Clear the result fields */
if( algorithm != NULL )
*algorithm = CRYPT_ALGO_NONE;
if( subAlgorithm != NULL )
*subAlgorithm = CRYPT_ALGO_NONE;
if( extraLength != NULL )
*extraLength = 0;
/* Determine the algorithm information based on the AlgorithmIdentifier
field */
readSequence( stream, &length );
status = readRawObject( stream, buffer, &bufferLength, MAX_OID_SIZE,
BER_OBJECT_IDENTIFIER );
if( cryptStatusError( status ) )
return( status );
length -= bufferLength;
if( ( cryptAlgo = oidToAlgorithm( buffer, &cryptSubAlgo ) ) == CRYPT_ERROR )
return( CRYPT_ERROR_NOTAVAIL );
if( algorithm != NULL )
*algorithm = cryptAlgo;
if( subAlgorithm != NULL )
*subAlgorithm = cryptSubAlgo;
/* Handle any remaining parameters */
if( length == sizeofNull() )
/* Skip the algorithm parameters field */
status = readNull( stream );
else
/* Tell the caller how much remains to be read */
if( extraLength != NULL )
*extraLength = ( int ) length;
return( status );
}
int readAlgoID( STREAM *stream, CRYPT_ALGO *algorithm )
{
return( readAlgoIDex( stream, algorithm, NULL, NULL ) );
}
/* Determine the size of an AlgorithmIdentifier record from an encryption
context */
int sizeofContextAlgoID( const CRYPT_CONTEXT iCryptContext,
const CRYPT_ALGO subAlgorithm,
const int flags )
{
int cryptAlgo, status;
/* If it's a standard write, determine how large the algoID and
parameters are. Because this is a rather complex operation, the
easiest way to do it is to write to a null stream and get its
size */
if( flags == ALGOID_FLAG_NONE )
{
STREAM nullStream;
sMemOpen( &nullStream, NULL, 0 );
status = writeContextAlgoID( &nullStream, iCryptContext,
subAlgorithm, ALGOID_FLAG_NONE );
if( cryptStatusOK( status ) )
status = ( int ) stell( &nullStream );
sMemClose( &nullStream );
return( status );
}
assert( flags == ALGOID_FLAG_ALGOID_ONLY );
/* Write the algoID only */
status = krnlSendMessage( iCryptContext, RESOURCE_IMESSAGE_GETATTRIBUTE,
&cryptAlgo, CRYPT_CTXINFO_ALGO );
if( cryptStatusError( status ) )
return( status );
return( sizeofAlgoIDex( cryptAlgo, subAlgorithm, 0 ) );
}
/* Write an AlgorithmIdentifier record from an encryption context */
int writeContextAlgoID( STREAM *stream, const CRYPT_CONTEXT iCryptContext,
const CRYPT_ALGO subAlgorithm,
const int flags )
{
int cryptAlgo, status;
status = krnlSendMessage( iCryptContext, RESOURCE_IMESSAGE_GETATTRIBUTE,
&cryptAlgo, CRYPT_CTXINFO_ALGO );
if( cryptStatusError( status ) )
return( status );
if( flags & ALGOID_FLAG_ALGOID_ONLY )
return( writeAlgoIDex( stream, cryptAlgo, subAlgorithm, 0 ) );
/* If we're writing parameters such as key and block sizes and IV
alongside the algorithm identifier, it has to be a conventional
context */
assert( subAlgorithm == CRYPT_ALGO_NONE );
assert( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \
cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL );
return( writeContextCryptAlgoID( stream, iCryptContext ) );
}
/* Turn an AlgorithmIdentifier into a hash/encryption context */
int readContextAlgoID( STREAM *stream, CRYPT_CONTEXT *iCryptContext,
QUERY_INFO *queryInfo, const int tag )
{
QUERY_INFO localQueryInfo, *queryInfoPtr = ( queryInfo == NULL ) ? \
&localQueryInfo : queryInfo;
MESSAGE_CREATEOBJECT_INFO createInfo;
int status;
/* Read the algorithm info. If we're not creating a context from the
info, we're done */
if( iCryptContext != NULL )
*iCryptContext = CRYPT_ERROR;
status = readAlgoIDInfo( stream, queryInfoPtr, tag );
if( cryptStatusError( status ) || iCryptContext == NULL )
{
if( status == CRYPT_ERROR_BADDATA || status == CRYPT_ERROR_UNDERFLOW )
/* It's a stream-related error, make it persistent */
sSetError( stream, status );
return( status );
}
/* Create the object from it */
setMessageCreateObjectInfo( &createInfo, queryInfoPtr->cryptAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
RESOURCE_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 );
}
status = krnlSendMessage( createInfo.cryptHandle,
RESOURCE_IMESSAGE_SETATTRIBUTE,
&queryInfoPtr->cryptMode, CRYPT_CTXINFO_MODE );
if( cryptStatusOK( status ) && \
!isStreamCipher( queryInfoPtr->cryptAlgo ) )
{
RESOURCE_DATA msgData;
int ivLength;
status = krnlSendMessage( createInfo.cryptHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE,
&ivLength, CRYPT_CTXINFO_IVSIZE );
setResourceData( &msgData, queryInfoPtr->iv,
min( ivLength, queryInfoPtr->ivLength ) );
if( cryptStatusOK( status ) )
status = krnlSendMessage( createInfo.cryptHandle,
RESOURCE_IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_CTXINFO_IV );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -