📄 res_env.c
字号:
status = checkActionIndirect( envelopeInfoPtr->postActionList,
checkSignatureActionFunction,
signingKeyPresent );
if( cryptStatusError( status ) )
{
setErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_SIGNATURE,
CRYPT_ERRTYPE_ATTR_ABSENT );
return( status );
}
}
return( CRYPT_OK );
}
/****************************************************************************
* *
* Add Enveloping Information *
* *
****************************************************************************/
/* Add keyset information (this function is also used by the de-enveloping
routines) */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int addKeysetInfo( INOUT ENVELOPE_INFO *envelopeInfoPtr,
IN_RANGE( CRYPT_ENVINFO_KEYSET_ENCRYPT, \
CRYPT_ENVINFO_KEYSET_SIGCHECK ) \
const CRYPT_ATTRIBUTE_TYPE keysetFunction,
IN_HANDLE const CRYPT_KEYSET keyset )
{
CRYPT_KEYSET *iKeysetPtr;
assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
REQUIRES( keysetFunction == CRYPT_ENVINFO_KEYSET_ENCRYPT || \
keysetFunction == CRYPT_ENVINFO_KEYSET_DECRYPT || \
keysetFunction == CRYPT_ENVINFO_KEYSET_SIGCHECK );
REQUIRES( isHandleRangeValid( keyset ) );
/* Figure out which keyset we want to set */
switch( keysetFunction )
{
case CRYPT_ENVINFO_KEYSET_ENCRYPT:
iKeysetPtr = &envelopeInfoPtr->iEncryptionKeyset;
break;
case CRYPT_ENVINFO_KEYSET_DECRYPT:
iKeysetPtr = &envelopeInfoPtr->iDecryptionKeyset;
break;
case CRYPT_ENVINFO_KEYSET_SIGCHECK:
iKeysetPtr = &envelopeInfoPtr->iSigCheckKeyset;
break;
default:
retIntError();
}
/* Make sure that the keyset hasn't already been set */
if( *iKeysetPtr != CRYPT_ERROR )
{
setErrorInfo( envelopeInfoPtr, keysetFunction,
CRYPT_ERRTYPE_ATTR_PRESENT );
return( CRYPT_ERROR_INITED );
}
/* Remember the new keyset and increment its reference count */
*iKeysetPtr = keyset;
return( krnlSendNotifier( keyset, IMESSAGE_INCREFCOUNT ) );
}
/* Add an encryption password */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int addPasswordInfo( ENVELOPE_INFO *envelopeInfoPtr,
IN_BUFFER( passwordLength ) const void *password,
IN_RANGE( 1, CRYPT_MAX_TEXTSIZE ) \
const int passwordLength )
{
CRYPT_ALGO_TYPE cryptAlgo = envelopeInfoPtr->defaultAlgo;
CRYPT_CONTEXT iCryptContext;
MESSAGE_CREATEOBJECT_INFO createInfo;
MESSAGE_DATA msgData;
ACTION_RESULT actionResult;
int status;
assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
assert( isReadPtr( password, passwordLength ) );
REQUIRES( passwordLength > 0 && passwordLength <= CRYPT_MAX_TEXTSIZE );
REQUIRES( envelopeInfoPtr->type != CRYPT_FORMAT_PGP );
/* Make sure that we can still add another action */
if( !moreActionsPossible( envelopeInfoPtr->preActionList ) )
return( CRYPT_ERROR_OVERFLOW );
/* Create the appropriate encryption context. We have to be careful to
ensure that we use an algorithm which is compatible with the wrapping
mechanism */
if( isStreamCipher( cryptAlgo ) || \
cryptStatusError( sizeofAlgoIDex( cryptAlgo, CRYPT_MODE_CBC, 0 ) ) )
cryptAlgo = CRYPT_ALGO_3DES;
setMessageCreateObjectInfo( &createInfo, cryptAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
if( cryptStatusError( status ) )
return( status );
iCryptContext = createInfo.cryptHandle;
/* Derive the key into the context */
setMessageData( &msgData, ( void * ) password, passwordLength );
status = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_CTXINFO_KEYING_VALUE );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
return( status );
}
/* Make sure that this key exchange action isn't already present and
insert it into the action list */
actionResult = checkAction( envelopeInfoPtr->preActionList,
ACTION_KEYEXCHANGE, iCryptContext );
if( actionResult == ACTION_RESULT_ERROR || \
actionResult == ACTION_RESULT_INITED )
{
setErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_PASSWORD,
CRYPT_ERRTYPE_ATTR_PRESENT );
status = CRYPT_ERROR_INITED;
}
else
{
status = addAction( &envelopeInfoPtr->preActionList,
envelopeInfoPtr->memPoolState,
ACTION_KEYEXCHANGE, iCryptContext );
}
if( cryptStatusError( status ) )
krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
return( status );
}
#ifdef USE_PGP
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int addPgpPasswordInfo( ENVELOPE_INFO *envelopeInfoPtr,
IN_BUFFER( passwordLength ) const void *password,
IN_RANGE( 1, CRYPT_MAX_TEXTSIZE ) \
const int passwordLength )
{
CRYPT_ALGO_TYPE cryptAlgo = envelopeInfoPtr->defaultAlgo;
CRYPT_CONTEXT iCryptContext;
MESSAGE_CREATEOBJECT_INFO createInfo;
MESSAGE_DATA msgData;
BYTE salt[ PGP_SALTSIZE + 8 ];
static const CRYPT_MODE_TYPE mode = CRYPT_MODE_CFB;
int status;
assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
assert( isReadPtr( password, passwordLength ) );
REQUIRES( passwordLength > 0 && passwordLength <= CRYPT_MAX_TEXTSIZE );
REQUIRES( envelopeInfoPtr->type == CRYPT_FORMAT_PGP );
/* Make sure that we can still add another attribute */
if( !moreActionsPossible( envelopeInfoPtr->preActionList ) )
return( CRYPT_ERROR_OVERFLOW );
/* PGP doesn't support both PKC and conventional key exchange actions or
multiple conventional key exchange actions in the same envelope since
the session key is encrypted for the PKC action but derived from the
password for the conventional action */
if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && \
( findAction( envelopeInfoPtr->preActionList,
ACTION_KEYEXCHANGE_PKC ) != NULL || \
envelopeInfoPtr->actionList != NULL ) )
{
setErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_PUBLICKEY,
CRYPT_ERRTYPE_ATTR_PRESENT );
return( CRYPT_ERROR_INITED );
}
/* Create the appropriate encryption context. PGP wrapping always uses
CFB mode (so there are no modes that need to be avoided) and the
higher-level code has constrained the algorithm type to something
that's encodable using the PGP data format so we don't need to
perform any additional checking here */
setMessageCreateObjectInfo( &createInfo, cryptAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
if( cryptStatusError( status ) )
return( status );
iCryptContext = createInfo.cryptHandle;
/* PGP uses CFB mode for everything so we change the mode from the
default of CBC to CFB */
status = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE,
( void * ) &mode, CRYPT_CTXINFO_MODE );
if( cryptStatusError( status ) )
return( status );
/* Generate a salt and derive the key into the context */
setMessageData( &msgData, salt, PGP_SALTSIZE );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );
if( cryptStatusOK( status ) )
{
status = pgpPasswordToKey( iCryptContext, CRYPT_UNUSED,
password, passwordLength,
envelopeInfoPtr->defaultHash,
salt, PGP_SALTSIZE, PGP_ITERATIONS );
}
if( cryptStatusError( status ) )
{
krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
return( status );
}
/* Insert the context into the action list. Since PGP doesn't perform a
key exchange of a session key we insert the password-derived context
directly into the main action list */
status = addAction( &envelopeInfoPtr->actionList,
envelopeInfoPtr->memPoolState, ACTION_CRYPT,
iCryptContext );
if( cryptStatusError( status ) )
krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
return( status );
}
#endif /* USE_PGP */
/* Add a context to an envelope */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
static int addContextInfo( INOUT ENVELOPE_INFO *envelopeInfoPtr,
IN_HANDLE const CRYPT_HANDLE cryptHandle,
INOUT_PTR ACTION_LIST **actionListHeadPtrPtr,
IN_ENUM( ACTION ) const ACTION_TYPE actionType )
{
CRYPT_ALGO_TYPE cryptAlgo, certHashAlgo;
CRYPT_MODE_TYPE cryptMode = CRYPT_MODE_NONE;
CRYPT_HANDLE iCryptHandle = cryptHandle;
ACTION_LIST *actionListPtr, *hashActionPtr;
ACTION_RESULT actionResult;
int status;
assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
assert( isWritePtr( actionListHeadPtrPtr, sizeof( ACTION_LIST * ) ) );
REQUIRES( isHandleRangeValid( cryptHandle ) );
REQUIRES( actionType > ACTION_NONE && actionType < ACTION_LAST );
/* Make sure that we can still add another attribute */
if( !moreActionsPossible( envelopeInfoPtr->preActionList ) )
return( CRYPT_ERROR_OVERFLOW );
/* Make sure that the algorithm information is encodable using the
selected envelope format. This should already have been checked by
the calling function but we double-check here because this provides
a convenient centralised location for it */
status = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE,
&cryptAlgo, CRYPT_CTXINFO_ALGO );
if( cryptStatusOK( status ) && \
( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \
cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL ) )
{
status = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE,
&cryptMode, CRYPT_CTXINFO_MODE );
}
if( cryptStatusError( status ) )
return( status );
if( !envelopeInfoPtr->checkAlgo( cryptAlgo, cryptMode ) )
return( CRYPT_ARGERROR_NUM1 );
/* Find the insertion point for this action and make sure that it isn't
already present. The difference between ACTION_RESULT_INITED and
ACTION_RESULT_PRESENT is that an inited response indicates that the
user explicitly added the action and can't add it again while a
present response indicates that the action was added automatically by
cryptlib in response to the user adding some other action and
shouldn't be reported as an error, to the user it doesn't make any
difference whether the same action was added automatically by
cryptlib or explicitly */
actionResult = checkAction( *actionListHeadPtrPtr, actionType,
iCryptHandle );
switch( actionResult )
{
case ACTION_RESULT_OK:
case ACTION_RESULT_EMPTY:
break;
case ACTION_RESULT_INITED:
return( CRYPT_ERROR_INITED );
case ACTION_RESULT_PRESENT:
return( CRYPT_OK );
case ACTION_RESULT_ERROR:
return( CRYPT_ARGERROR_NUM1 );
default:
retIntError();
}
/* Insert the action into the list. If it's a non-idempotent context
(i.e. one whose state can change based on user actions) we clone it
for our own use, otherwise we just increment its reference count */
if( actionType == ACTION_HASH || actionType == ACTION_CRYPT )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
setMessageCreateObjectInfo( &createInfo, cryptAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_CONTEXT );
if( cryptStatusError( status ) )
return( status );
status = krnlSendMessage( iCryptHandle, IMESSAGE_CLONE, NULL,
createInfo.cryptHandle );
if( cryptStatusError( status ) )
{
krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
return( status );
}
iCryptHandle = createInfo.cryptHandle;
}
else
{
status = krnlSendNotifier( iCryptHandle, IMESSAGE_INCREFCOUNT );
if( cryptStatusError( status ) )
return( status );
}
status = addActionEx( &actionListPtr, actionListHeadPtrPtr,
envelopeInfoPtr->memPoolState, actionType,
iCryptHandle );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );
return( status );
}
if( actionType == ACTION_HASH )
{
/* Remember that we need to hook the hash action up to a signature
action before we start enveloping data */
actionListPtr->flags |= ACTION_NEEDSCONTROLLER;
}
/* If the newly-inserted action isn't a controlling action, we're done */
if( actionType != ACTION_SIGN )
return( status );
/* Check whether the hash algorithm used in the certificate attached to
the signing key is stronger than the one that's set for the envelope
as a whole and if it is, upgrade the envelope hash algo. This is
based on the fact that anyone who's able to verify the certificate
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -