📄 cryptmis.c
字号:
}
void *getMemPool( void *statePtr, const int size )
{
MEMPOOL_INFO *state = ( MEMPOOL_INFO * ) statePtr;
BYTE *allocPtr = state->storage;
const int allocSize = roundUp( size, sizeof( int ) );
assert( isWritePtr( state, sizeof( MEMPOOL_INFO ) ) );
assert( isWritePtr( state->storage, state->storageSize ) );
/* If we can't satisfy the request from the memory pool, we have to
allocate it dynamically */
if( state->storageSize - state->storagePos < allocSize )
return( clDynAlloc( "getMemPool", size ) );
/* We can satisfy the request from the pool */
allocPtr += state->storagePos;
state->storagePos += size;
return( allocPtr );
}
void freeMemPool( void *statePtr, void *memblock )
{
MEMPOOL_INFO *state = ( MEMPOOL_INFO * ) statePtr;
assert( isWritePtr( state, sizeof( MEMPOOL_INFO ) ) );
assert( isWritePtr( state->storage, state->storageSize ) );
/* If the memory block is within the pool, there's nothing to do */
if( memblock >= state->storage && \
memblock <= ( void * ) ( ( BYTE * ) state->storage + \
state->storageSize ) )
return;
/* It's outside the pool and therefore dynamically allocated, free it */
clFree( "freeMemPool", memblock );
}
/* Export attribute or certificate data to a stream. In theory we would
have to export this via a dynbuf and then write it to the stream, however
we can save some overhead by writing it directly to the stream's buffer */
int exportAttributeToStream( void *streamPtr, const CRYPT_HANDLE cryptHandle,
const CRYPT_ATTRIBUTE_TYPE attributeType )
{
RESOURCE_DATA msgData;
STREAM *stream = streamPtr;
int status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( sStatusOK( stream ) );
assert( checkHandleRange( cryptHandle ) );
assert( isAttribute( attributeType ) || \
isInternalAttribute( attributeType ) );
/* Before we try the export, make sure that everything is OK with the
stream */
if( !sStatusOK( stream ) )
return( sGetStatus( stream ) );
if( sMemDataLeft( stream ) < 2 )
return( CRYPT_ERROR_UNDERFLOW );
/* Export the attribute to the stream */
setMessageData( &msgData, sMemBufPtr( stream ), sMemDataLeft( stream ) );
status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,
&msgData, attributeType );
if( cryptStatusOK( status ) )
status = sSkip( stream, msgData.length );
return( status );
}
int exportCertToStream( void *streamPtr,
const CRYPT_CERTIFICATE cryptCertificate,
const CRYPT_CERTTYPE_TYPE certType )
{
RESOURCE_DATA msgData;
STREAM *stream = streamPtr;
int status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( sStatusOK( stream ) );
assert( checkHandleRange( cryptCertificate ) );
assert( certType > CRYPT_CERTTYPE_NONE && \
certType < CRYPT_CERTTYPE_LAST );
/* Before we try the export, make sure that everything is OK with the
stream */
if( !sStatusOK( stream ) )
return( sGetStatus( stream ) );
if( sMemDataLeft( stream ) < MIN_CRYPT_OBJECTSIZE )
return( CRYPT_ERROR_UNDERFLOW );
/* Export the cert to the stream */
setMessageData( &msgData, sMemBufPtr( stream ), sMemDataLeft( stream ) );
status = krnlSendMessage( cryptCertificate, IMESSAGE_CRT_EXPORT,
&msgData, certType );
if( cryptStatusOK( status ) )
status = sSkip( stream, msgData.length );
return( status );
}
/****************************************************************************
* *
* Enveloping Functions *
* *
****************************************************************************/
/* General-purpose enveloping functions, used by various high-level
protocols */
int envelopeWrap( const void *inData, const int inDataLength, void *outData,
int *outDataLength, const int outDataMaxLength,
const CRYPT_FORMAT_TYPE formatType,
const CRYPT_CONTENT_TYPE contentType,
const CRYPT_HANDLE iCryptKey )
{
CRYPT_ENVELOPE iCryptEnvelope;
MESSAGE_CREATEOBJECT_INFO createInfo;
RESOURCE_DATA msgData;
const int minBufferSize = max( MIN_BUFFER_SIZE, inDataLength + 512 );
int status;
assert( isReadPtr( inData, inDataLength ) );
assert( inDataLength > 16 );
assert( isWritePtr( outData, outDataMaxLength ) );
assert( outDataMaxLength > 16 );
assert( isWritePtr( outDataLength, sizeof( int ) ) );
assert( contentType == CRYPT_UNUSED || \
( contentType > CRYPT_CONTENT_NONE && \
contentType < CRYPT_CONTENT_LAST ) );
assert( ( iCryptKey == CRYPT_UNUSED ) || \
checkHandleRange( iCryptKey ) );
*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 ) )
return( status );
iCryptEnvelope = createInfo.cryptHandle;
krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,
( void * ) &minBufferSize, CRYPT_ATTRIBUTE_BUFFERSIZE );
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,
( void * ) &inDataLength,
CRYPT_ENVINFO_DATASIZE );
if( cryptStatusOK( status ) && contentType != CRYPT_UNUSED )
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,
( void * ) &contentType,
CRYPT_ENVINFO_CONTENTTYPE );
if( cryptStatusOK( status ) && iCryptKey != CRYPT_UNUSED )
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,
( void * ) &iCryptKey,
CRYPT_ENVINFO_PUBLICKEY );
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, ( void * ) inData, inDataLength );
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_PUSHDATA,
&msgData, 0 );
}
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 );
}
krnlSendNotifier( iCryptEnvelope, IMESSAGE_DECREFCOUNT );
if( cryptStatusOK( status ) )
*outDataLength = msgData.length;
return( status );
}
int envelopeUnwrap( const void *inData, const int inDataLength,
void *outData, int *outDataLength,
const int outDataMaxLength,
const CRYPT_CONTEXT iDecryptKey )
{
CRYPT_ENVELOPE iCryptEnvelope;
MESSAGE_CREATEOBJECT_INFO createInfo;
RESOURCE_DATA msgData;
const int minBufferSize = max( MIN_BUFFER_SIZE, inDataLength );
int status;
assert( isReadPtr( inData, inDataLength ) );
assert( inDataLength > 16 );
assert( isWritePtr( outData, outDataMaxLength ) );
assert( outDataMaxLength > 16 );
assert( isWritePtr( outDataLength, sizeof( int ) ) );
assert( ( iDecryptKey == CRYPT_UNUSED ) || \
checkHandleRange( iDecryptKey ) );
*outDataLength = 0;
/* Create an envelope to unwrap the data, add the decryption key if
necessary, and pop the unwrapped result */
setMessageCreateObjectInfo( &createInfo, CRYPT_FORMAT_AUTO );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_ENVELOPE );
if( cryptStatusError( status ) )
return( status );
iCryptEnvelope = createInfo.cryptHandle;
krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,
( void * ) &minBufferSize, CRYPT_ATTRIBUTE_BUFFERSIZE );
setMessageData( &msgData, ( void * ) inData, inDataLength );
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_PUSHDATA,
&msgData, 0 );
if( status == CRYPT_ENVELOPE_RESOURCE )
{
/* If the caller wasn't expecting encrypted data, let them know */
if( iDecryptKey == CRYPT_UNUSED )
status = CRYPT_ERROR_WRONGKEY;
else
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,
( void * ) &iDecryptKey,
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 );
}
krnlSendNotifier( iCryptEnvelope, IMESSAGE_DECREFCOUNT );
if( cryptStatusOK( status ) )
*outDataLength = msgData.length;
return( status );
}
int envelopeSign( const void *inData, const int inDataLength,
void *outData, int *outDataLength,
const int outDataMaxLength,
const CRYPT_CONTENT_TYPE contentType,
const CRYPT_CONTEXT iSigKey,
const CRYPT_CERTIFICATE iCmsAttributes )
{
CRYPT_ENVELOPE iCryptEnvelope;
MESSAGE_CREATEOBJECT_INFO createInfo;
RESOURCE_DATA msgData;
const int minBufferSize = max( MIN_BUFFER_SIZE, inDataLength + 1024 );
int status;
assert( isReadPtr( inData, inDataLength ) );
assert( inDataLength > 16 || \
( contentType == CRYPT_CONTENT_NONE && \
checkHandleRange( iCmsAttributes ) && \
inDataLength == 0 ) );
assert( isWritePtr( outData, outDataMaxLength ) );
assert( outDataMaxLength > 16 );
assert( isWritePtr( outDataLength, sizeof( int ) ) );
assert( contentType >= CRYPT_CONTENT_NONE && \
contentType < CRYPT_CONTENT_LAST );
assert( checkHandleRange( iSigKey ) );
assert( iCmsAttributes == CRYPT_UNUSED || \
checkHandleRange( iCmsAttributes ) );
*outDataLength = 0;
/* Create an envelope to sign the data, add the signature key and
optional signing attributes, and pop the signed result */
setMessageCreateObjectInfo( &createInfo, CRYPT_FORMAT_CMS );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_ENVELOPE );
if( cryptStatusError( status ) )
return( status );
iCryptEnvelope = createInfo.cryptHandle;
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 ) )
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,
( void * ) &iSigKey,
CRYPT_ENVINFO_SIGNATURE );
if( cryptStatusOK( status ) && iCmsAttributes != CRYPT_UNUSED )
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,
( void * ) &iCmsAttributes,
CRYPT_ENVINFO_SIGNATURE_EXTRADATA );
if( cryptStatusOK( status ) )
{
/* If there's no data supplied, it's an attributes-only message
containing only authenticated attributes */
if( inDataLength <= 0 )
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_TRUE,
CRYPT_IATTRIBUTE_ATTRONLY );
else
{
setMessageData( &msgData, ( void * ) inData, inDataLength );
status = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_PUSHDATA,
&msgData, 0 );
}
}
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 );
}
krnlSendNotifier( iCryptEnvelope, IMESSAGE_DECREFCOUNT );
if( cryptStatusOK( status ) )
*outDataLength = msgData.length;
return( status );
}
int envelopeSigCheck( const void *inData, const int inDataLength,
void *outData, int *outDataLength,
const int outDataMaxLength,
const CRYPT_CONTEXT iSigCheckKey,
int *sigResult, CRYPT_CERTIFICATE *iSigningCert,
CRYPT_CERTIFICATE *iCmsAttributes )
{
CRYPT_ENVELOPE iCryptEnvelope;
MESSAGE_CREATEOBJECT_INFO createInfo;
RESOURCE_DATA msgData;
const int minBufferSize = max( MIN_BUFFER_SIZE, inDataLength );
int status;
assert( isReadPtr( inData, inDataLength ) );
assert( inDataLength > 16 );
assert( isWritePtr( outData, outDataMaxLength ) );
assert( outDataMaxLength > 16 );
assert( isWritePtr( outDataLength, sizeof( int ) ) );
assert( iSigCheckKey == CRYPT_UNUSED || \
checkHandleRange( iSigCheckKey ) );
assert( isWritePtr( sigResult, sizeof( int ) ) );
/* Clear return values */
*outDataLength = 0;
*sigResult = CRYPT_ERROR;
if( iSigningCert != NULL )
*iSigningCert = CRYPT_ERROR;
if( iCmsAttributes != NULL )
*iCmsAttributes = CRYPT_ERROR;
/* Create an envelope to sig.check the data, push in the signed data and
sig.check key, and pop the result. We also speculatively set the
attributes-only flag to let the enveloping code know that a signed
message with no content is a zero-data-length message rather than a
detached signature, which is what this type of message would normally
be */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -