📄 int_env.c
字号:
/****************************************************************************
* *
* cryptlib Internal Enveloping API *
* Copyright Peter Gutmann 1992-2008 *
* *
****************************************************************************/
#include "crypt.h"
#ifndef NDEBUG /* For assert( checkObjectEncoding() ) */
#if defined( INC_ALL )
#include "asn1.h"
#else
#include "misc/asn1.h"
#endif /* Compiler-specific includes */
#endif /* NDEBUG */
/****************************************************************************
* *
* Data Wrap/Unwrap Functions *
* *
****************************************************************************/
/* General-purpose enveloping functions, used by various high-level
protocols */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \
int envelopeWrap( IN_BUFFER( inDataLength ) const void *inData,
IN_LENGTH_MIN( 16 ) const int inDataLength,
OUT_BUFFER( outDataMaxLength, \
*outDataLength ) void *outData,
IN_LENGTH_MIN( 16 ) const int outDataMaxLength,
OUT_LENGTH_Z int *outDataLength,
IN_ENUM( CRYPT_FORMAT ) const CRYPT_FORMAT_TYPE formatType,
IN_ENUM_OPT( CRYPT_CONTENT ) \
const CRYPT_CONTENT_TYPE contentType,
IN_HANDLE_OPT const CRYPT_HANDLE iPublicKey )
{
CRYPT_ENVELOPE iCryptEnvelope;
MESSAGE_CREATEOBJECT_INFO createInfo;
MESSAGE_DATA msgData;
const int minBufferSize = max( MIN_BUFFER_SIZE, inDataLength + 512 );
int status;
assert( isReadPtr( inData, inDataLength ) );
assert( isWritePtr( outData, outDataMaxLength ) );
assert( isWritePtr( outDataLength, sizeof( int ) ) );
REQUIRES( inDataLength > 16 && inDataLength < MAX_INTLENGTH );
REQUIRES( outDataMaxLength > 16 && \
outDataMaxLength >= inDataLength + 512 && \
outDataMaxLength < MAX_INTLENGTH );
REQUIRES( formatType == CRYPT_FORMAT_CRYPTLIB || \
formatType == CRYPT_FORMAT_CMS );
REQUIRES( contentType >= CRYPT_CONTENT_NONE && \
contentType < CRYPT_CONTENT_LAST );
REQUIRES( ( iPublicKey == CRYPT_UNUSED ) || \
isHandleRangeValid( iPublicKey ) );
/* Clear return values. Note that we can't clear the output buffer
at this point since this function is frequently used for in-place
processing, so we clear it after we've pushed the input data */
*outDataLength = 0;
/* Create an envelope to wrap the data, add the encryption key if
necessary, and pop the wrapped result */
setMessageCreateObjectInfo( &createInfo, formatType );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_ENVELOPE );
if( cryptStatusError( status ) )
{
memset( outData, 0, min( 16, outDataMaxLength ) );
return( status );
}
iCryptEnvelope = createInfo.cryptHandle;
( void ) krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,
( void * ) &minBufferSize,
CRYPT_ATTRIBUTE_BUFFERSIZE );
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,
( void * ) &inDataLength,
CRYPT_ENVINFO_DATASIZE );
if( cryptStatusOK( status ) && contentType != CRYPT_CONTENT_NONE )
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,
( void * ) &contentType,
CRYPT_ENVINFO_CONTENTTYPE );
if( cryptStatusOK( status ) && iPublicKey != CRYPT_UNUSED )
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,
( void * ) &iPublicKey,
CRYPT_ENVINFO_PUBLICKEY );
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, ( void * ) inData, inDataLength );
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_PUSHDATA,
&msgData, 0 );
if( cryptStatusOK( status ) )
{
ENSURES( msgData.length >= inDataLength );
}
}
memset( outData, 0, min( 16, outDataMaxLength ) );
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, NULL, 0 );
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_PUSHDATA,
&msgData, 0 );
}
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, outData, outDataMaxLength );
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_POPDATA,
&msgData, 0 );
if( cryptStatusOK( status ) )
{
ENSURES( msgData.length > inDataLength && \
msgData.length < outDataMaxLength );
}
if( cryptStatusOK( status ) )
*outDataLength = msgData.length;
}
krnlSendNotifier( iCryptEnvelope, IMESSAGE_DECREFCOUNT );
assert( cryptStatusError( status ) || \
!cryptStatusError( checkObjectEncoding( outData, \
*outDataLength ) ) );
assert( !cryptArgError( status ) );
return( cryptArgError( status ) ? CRYPT_ERROR_BADDATA : status );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \
int envelopeUnwrap( IN_BUFFER( inDataLength ) const void *inData,
IN_LENGTH_MIN( 16 ) const int inDataLength,
OUT_BUFFER( outDataMaxLength, \
*outDataLength ) void *outData,
IN_LENGTH_MIN( 16 ) const int outDataMaxLength,
OUT_LENGTH_Z int *outDataLength,
IN_HANDLE_OPT const CRYPT_CONTEXT iPrivKey )
{
CRYPT_ENVELOPE iCryptEnvelope;
MESSAGE_CREATEOBJECT_INFO createInfo;
MESSAGE_DATA msgData;
const int minBufferSize = max( MIN_BUFFER_SIZE, inDataLength );
int status;
assert( isReadPtr( inData, inDataLength ) );
assert( isWritePtr( outData, outDataMaxLength ) );
assert( isWritePtr( outDataLength, sizeof( int ) ) );
REQUIRES( inDataLength > 16 && inDataLength < MAX_INTLENGTH );
REQUIRES( outDataMaxLength > 16 && \
outDataMaxLength >= inDataLength && \
outDataMaxLength < MAX_INTLENGTH );
REQUIRES( ( iPrivKey == CRYPT_UNUSED ) || \
isHandleRangeValid( iPrivKey ) );
/* Clear return values. Note that we can't clear the output buffer
at this point since this function is frequently used for in-place
processing, so we clear it after we've pushed the input data */
*outDataLength = 0;
/* Create an envelope to unwrap the data, add the decryption key if
necessary, and pop the unwrapped result. In theory we could use
checkASN1() here to perform a safety check of the envelope data
prior to processing but this has already been done by the calling
code when the datagram containing the enveloped data was read so
we don't need to repeat the (rather heavyweight) operation here */
setMessageCreateObjectInfo( &createInfo, CRYPT_FORMAT_AUTO );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_ENVELOPE );
if( cryptStatusError( status ) )
{
memset( outData, 0, min( 16, outDataMaxLength ) );
return( status );
}
iCryptEnvelope = createInfo.cryptHandle;
( void ) krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,
( void * ) &minBufferSize,
CRYPT_ATTRIBUTE_BUFFERSIZE );
setMessageData( &msgData, ( void * ) inData, inDataLength );
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_PUSHDATA,
&msgData, 0 );
if( cryptStatusOK( status ) )
{
ENSURES( msgData.length >= inDataLength );
}
memset( outData, 0, min( 16, outDataMaxLength ) );
if( status == CRYPT_ENVELOPE_RESOURCE )
{
/* If the caller wasn't expecting encrypted data, let them know */
if( iPrivKey == CRYPT_UNUSED )
status = CRYPT_ERROR_WRONGKEY;
else
{
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,
( void * ) &iPrivKey,
CRYPT_ENVINFO_PRIVATEKEY );
}
}
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, NULL, 0 );
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_PUSHDATA,
&msgData, 0 );
}
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, outData, outDataMaxLength );
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_POPDATA,
&msgData, 0 );
if( cryptStatusOK( status ) )
{
ENSURES( msgData.length < inDataLength && \
msgData.length < outDataMaxLength );
}
}
krnlSendNotifier( iCryptEnvelope, IMESSAGE_DECREFCOUNT );
if( cryptStatusOK( status ) )
*outDataLength = msgData.length;
assert( !cryptArgError( status ) );
return( cryptArgError( status ) ? CRYPT_ERROR_BADDATA : status );
}
/****************************************************************************
* *
* Data Sign/Verify Functions *
* *
****************************************************************************/
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \
int envelopeSign( IN_BUFFER( inDataLength ) const void *inData,
IN_LENGTH_MIN( 16 ) const int inDataLength,
OUT_BUFFER( outDataMaxLength, \
*outDataLength ) void *outData,
IN_LENGTH_MIN( 16 ) const int outDataMaxLength,
OUT_LENGTH_Z int *outDataLength,
IN_ENUM_OPT( CRYPT_CONTENT ) \
const CRYPT_CONTENT_TYPE contentType,
IN_HANDLE const CRYPT_CONTEXT iSigKey,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -