📄 cryptenv.c
字号:
{
CRYPT_HANDLE iCryptHandle;
CONTENT_LIST *contentListItem = \
envelopeInfoPtr->contentListCurrent;
assert( contentListItem != NULL );
/* Make sure that there's extra data present */
iCryptHandle = \
( messageValue == CRYPT_ENVINFO_SIGNATURE_EXTRADATA ) ? \
contentListItem->clSigInfo.iExtraData : \
contentListItem->clSigInfo.iTimestamp;
if( iCryptHandle == CRYPT_ERROR )
return( exitErrorNotFound( envelopeInfoPtr, messageValue ) );
/* Return it to the caller */
krnlSendNotifier( iCryptHandle, IMESSAGE_INCREFCOUNT );
*valuePtr = iCryptHandle;
return( CRYPT_OK );
}
case CRYPT_IATTRIBUTE_ATTRONLY:
/* If this isn't signed data, we don't know whether it's an
attributes-only message or not */
if( envelopeInfoPtr->usage != ACTION_SIGN )
return( exitErrorNotFound( envelopeInfoPtr,
CRYPT_IATTRIBUTE_ATTRONLY ) );
*valuePtr = ( envelopeInfoPtr->flags & ENVELOPE_ATTRONLY ) ? \
TRUE : FALSE;
return( CRYPT_OK );
}
assert( NOTREACHED );
return( CRYPT_ERROR ); /* Get rid of compiler warning */
}
static int processGetAttributeS( ENVELOPE_INFO *envelopeInfoPtr,
void *messageDataPtr, const int messageValue )
{
CONTENT_LIST *contentListItem;
int status;
/* If we're querying something that resides in the content list, make
sure there's a content list present. If it's present but nothing is
selected, select the first entry */
if( messageValue == CRYPT_ENVINFO_PRIVATEKEY_LABEL && \
envelopeInfoPtr->contentListCurrent == NULL )
{
if( envelopeInfoPtr->contentList == NULL )
return( exitErrorNotFound( envelopeInfoPtr,
CRYPT_ENVINFO_PRIVATEKEY_LABEL ) );
envelopeInfoPtr->contentListCurrent = envelopeInfoPtr->contentList;
resetVirtualCursor( envelopeInfoPtr->contentListCurrent );
}
/* Generic attributes are valid for all envelope types */
if( messageValue == CRYPT_ENVINFO_PRIVATEKEY_LABEL )
{
MESSAGE_KEYMGMT_INFO getkeyInfo;
char label[ CRYPT_MAX_TEXTSIZE ];
/* Make sure that the current required resource is a private key and
that there's a keyset available to pull the key from */
contentListItem = envelopeInfoPtr->contentListCurrent;
if( contentListItem->envInfo != CRYPT_ENVINFO_PRIVATEKEY )
return( exitErrorNotFound( envelopeInfoPtr,
CRYPT_ENVINFO_PRIVATEKEY_LABEL ) );
if( envelopeInfoPtr->iDecryptionKeyset == CRYPT_ERROR )
return( exitErrorNotInited( envelopeInfoPtr,
CRYPT_ENVINFO_KEYSET_DECRYPT ) );
/* Try and get the key label information. Since we're accessing the
key by (unique) key ID, there's no real need to specify a
preference for encryption keys */
if( contentListItem->issuerAndSerialNumber == NULL )
{
setMessageKeymgmtInfo( &getkeyInfo,
( contentListItem->formatType == CRYPT_FORMAT_PGP ) ? \
CRYPT_IKEYID_PGPKEYID : CRYPT_IKEYID_KEYID,
contentListItem->keyID,
contentListItem->keyIDsize,
label, CRYPT_MAX_TEXTSIZE,
KEYMGMT_FLAG_LABEL_ONLY );
}
else
{
setMessageKeymgmtInfo( &getkeyInfo,
CRYPT_IKEYID_ISSUERANDSERIALNUMBER,
contentListItem->issuerAndSerialNumber,
contentListItem->issuerAndSerialNumberSize,
label, CRYPT_MAX_TEXTSIZE,
KEYMGMT_FLAG_LABEL_ONLY );
}
status = krnlSendMessage( envelopeInfoPtr->iDecryptionKeyset,
IMESSAGE_KEY_GETKEY, &getkeyInfo,
KEYMGMT_ITEM_PRIVATEKEY );
if( cryptStatusOK( status ) )
return( attributeCopy( messageDataPtr, getkeyInfo.auxInfo,
getkeyInfo.auxInfoLength ) );
return( status );
}
assert( NOTREACHED );
return( CRYPT_ERROR ); /* Get rid of compiler warning */
}
static int processSetAttribute( ENVELOPE_INFO *envelopeInfoPtr,
void *messageDataPtr, const int messageValue )
{
MESSAGE_CHECK_TYPE checkType = MESSAGE_CHECK_NONE;
ACTION_TYPE usage = ACTION_NONE;
static const struct {
const CRYPT_ATTRIBUTE_TYPE type; /* Attribute type */
const ACTION_TYPE usage; /* Corresponding usage type */
const MESSAGE_CHECK_TYPE checkType; /* and check type */
} checkTable[] = {
#ifdef USE_COMPRESSION
{ CRYPT_ENVINFO_COMPRESSION, ACTION_COMPRESS, MESSAGE_CHECK_NONE },
#endif /* USE_COMPRESSION */
{ CRYPT_ENVINFO_MAC, ACTION_MAC, MESSAGE_CHECK_MAC },
{ CRYPT_ENVINFO_KEY, ACTION_CRYPT, MESSAGE_CHECK_CRYPT },
{ CRYPT_ENVINFO_PUBLICKEY, ACTION_CRYPT, MESSAGE_CHECK_PKC_ENCRYPT },
{ CRYPT_ENVINFO_PRIVATEKEY, ACTION_CRYPT, MESSAGE_CHECK_PKC_DECRYPT },
{ CRYPT_ENVINFO_SESSIONKEY, ACTION_CRYPT, MESSAGE_CHECK_CRYPT },
{ CRYPT_ENVINFO_HASH, ACTION_SIGN, MESSAGE_CHECK_HASH },
{ CRYPT_ENVINFO_TIMESTAMP, ACTION_SIGN, MESSAGE_CHECK_NONE },
{ CRYPT_ENVINFO_DETACHEDSIGNATURE, ACTION_SIGN, MESSAGE_CHECK_NONE },
{ CRYPT_IATTRIBUTE_INCLUDESIGCERT, ACTION_SIGN, MESSAGE_CHECK_NONE },
{ CRYPT_IATTRIBUTE_ATTRONLY, ACTION_SIGN, MESSAGE_CHECK_NONE },
{ CRYPT_ATTRIBUTE_NONE, ACTION_NONE }
};
const int value = *( int * ) messageDataPtr;
int i, status;
/* If it's an initialisation message, there's nothing to do */
if( messageValue == CRYPT_IATTRIBUTE_INITIALISED )
return( CRYPT_OK );
/* Generic attributes are valid for all envelope types */
if( messageValue == CRYPT_ATTRIBUTE_BUFFERSIZE )
{
envelopeInfoPtr->bufSize = value;
return( CRYPT_OK );
}
/* If it's meta-information, process it now */
if( messageValue == CRYPT_ATTRIBUTE_CURRENT_GROUP || \
messageValue == CRYPT_ATTRIBUTE_CURRENT )
{
const CONTENT_LIST *contentListCursor;
/* If it's an absolute positioning code, pre-set the attribute
cursor if required */
if( value == CRYPT_CURSOR_FIRST || value == CRYPT_CURSOR_LAST )
{
if( envelopeInfoPtr->contentList == NULL )
return( CRYPT_ERROR_NOTFOUND );
/* If it's an absolute attribute positioning code, reset the
attribute cursor to the start of the list before we try to
move it, and if it's an attribute positioning code,
initialise the attribute cursor if necessary */
if( messageValue == CRYPT_ATTRIBUTE_CURRENT_GROUP || \
envelopeInfoPtr->contentListCurrent == NULL )
{
envelopeInfoPtr->contentListCurrent = \
envelopeInfoPtr->contentList;
resetVirtualCursor( envelopeInfoPtr->contentListCurrent );
}
/* If there are no attributes present, return the appropriate
error code */
if( envelopeInfoPtr->contentListCurrent == NULL )
return( ( value == CRYPT_CURSOR_FIRST || \
value == CRYPT_CURSOR_LAST ) ? \
CRYPT_ERROR_NOTFOUND : CRYPT_ERROR_NOTINITED );
}
else
/* It's a relative positioning code, return a not-inited error
rather than a not-found error if the cursor isn't set since
there may be attributes present but the cursor hasn't been
initialised yet by selecting the first or last absolute
attribute */
if( envelopeInfoPtr->contentListCurrent == NULL )
return( CRYPT_ERROR_NOTINITED );
/* Move the cursor */
contentListCursor = \
attributeMoveCursor( envelopeInfoPtr->contentListCurrent,
getAttrFunction, messageValue, value );
if( contentListCursor == NULL )
return( CRYPT_ERROR_NOTFOUND );
envelopeInfoPtr->contentListCurrent = \
( CONTENT_LIST * ) contentListCursor;
return( CRYPT_OK );
}
/* In general we can't add new enveloping information once we've started
processing data */
if( envelopeInfoPtr->state != STATE_PREDATA )
{
/* We can't add new information once we've started enveloping */
if( !( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) )
return( CRYPT_ERROR_INITED );
/* We can only add signature check information once we've started
de-enveloping */
if( messageValue != CRYPT_ENVINFO_SIGNATURE )
return( CRYPT_ERROR_INITED );
}
/* If we're de-enveloping PGP data, make sure that the attribute is
valid for PGP envelopes. We can't perform this check via the ACLs
because the data type isn't known at envelope creation time, so
there's a single generic de-envelope type for which the ACLs allow
the union of all de-enveloping attribute types. The following check
weeds out the ones that don't work for PGP */
if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP )
{
if( messageValue == CRYPT_OPTION_ENCR_MAC || \
messageValue == CRYPT_ENVINFO_MAC || \
messageValue == CRYPT_ENVINFO_KEY || \
messageValue == CRYPT_ENVINFO_SESSIONKEY )
return( CRYPT_ARGERROR_VALUE );
if( messageValue == CRYPT_ENVINFO_HASH && \
!( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG ) )
/* We can add a hash if we're creating a detached signature */
return( CRYPT_ARGERROR_VALUE );
}
/* Since the information may not be used for quite some time after it's
added, we do some preliminary checking here to allow us to return an
error code immediately rather than from some deeply-buried function an
indeterminate time in the future. Since much of the checking is
similar, we use a table-driven check for most types and fall back to
custom checking for special cases */
for( i = 0; checkTable[ i ].type != ACTION_NONE; i++ )
if( checkTable[ i ].type == messageValue )
{
if( envelopeInfoPtr->usage != ACTION_NONE && \
envelopeInfoPtr->usage != checkTable[ i ].usage )
return( exitErrorInited( envelopeInfoPtr, messageValue ) );
usage = checkTable[ i ].usage;
checkType = checkTable[ i ].checkType;
break;
}
if( usage != ACTION_NONE )
{
/* Make sure that the usage requirements for the item that we're
about to add are consistent */
if( envelopeInfoPtr->usage != ACTION_NONE && \
envelopeInfoPtr->usage != usage )
return( exitErrorInited( envelopeInfoPtr,
messageValue ) );
}
else
{
/* If it's not a general class of action, perform special-case usage
checking */
switch( messageValue )
{
case CRYPT_OPTION_ENCR_ALGO:
if( cryptStatusError( \
envelopeInfoPtr->checkCryptAlgo( value,
isStreamCipher( value ) ? CRYPT_MODE_OFB : \
( envelopeInfoPtr->type == CRYPT_FORMAT_PGP ) ? \
CRYPT_MODE_CFB : CRYPT_MODE_CBC ) ) )
return( CRYPT_ARGERROR_VALUE );
envelopeInfoPtr->defaultAlgo = value;
return( CRYPT_OK );
case CRYPT_OPTION_ENCR_HASH:
if( cryptStatusError( \
envelopeInfoPtr->checkHashAlgo( value ) ) )
return( CRYPT_ARGERROR_VALUE );
envelopeInfoPtr->defaultHash = value;
return( CRYPT_OK );
case CRYPT_OPTION_ENCR_MAC:
if( cryptStatusError( \
envelopeInfoPtr->checkHashAlgo( value ) ) )
return( CRYPT_ARGERROR_VALUE );
envelopeInfoPtr->defaultMAC = value;
return( CRYPT_OK );
case CRYPT_ENVINFO_DATASIZE:
if( envelopeInfoPtr->payloadSize != CRYPT_UNUSED )
return( exitErrorInited( envelopeInfoPtr,
CRYPT_ENVINFO_DATASIZE ) );
break;
case CRYPT_ENVINFO_CONTENTTYPE:
/* Exactly what is supposed to happen when PGP is asked to
sign non-plain-data is ill-defined. No command-line PGP
option will generate this type of message, and the RFCs
don't specify the behaviour (in fact RFC 1991's
description of PGP signing is completely wrong). In
practice PGP hashes and signs the payload contents of a
PGP literal data packet, however if there are extra layers
of processing between the signing and literal packets (eg
compression or encryption), what gets hashed isn't
specified. If it's always the payload of the final
(literal) data packet, we'd have to be able to burrow down
through arbitrary amounts of further data and processing
in order to get to the payload data to hash (this also
makes things like mail gateways that only allow signed
messages through infeasible unless the gateway holds
everyone's private key in order to get at the plaintext to
hash). Because of this problem, we disallow any attempts
to set a content-type other than plain data if we're
signing a PGP-format message */
if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && \
envelopeInfoPtr->usage == ACTION_SIGN && \
value != CRYPT_CONTENT_DATA )
return( CRYPT_ARGERROR_VALUE );
/* For user-friendliness we allow overwriting a given content
type with the same type, which is useful for cases when
cryptlib automatically presets the type based on other
information */
if( envelopeInfoPtr->contentType && \
envelopeInfoPtr->contentType != value )
return( exitErrorInited( envelopeInfoPtr,
CRYPT_ENVINFO_CONTENTTYPE ) );
break;
case CRYPT_ENVINFO_SIGNATURE:
checkType = \
( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) ? \
MESSAGE_CHECK_PKC_SIGCHECK : MESSAGE_CHECK_PKC_SIGN;
if( envelopeInfoPtr->usage != ACTION_NONE && \
envelopeInfoPtr->usage != ACTION_SIGN )
return( exitErrorInited( envelopeInfoPtr,
CRYPT_ENVINFO_SIGNATURE ) );
if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && \
envelopeInfoPtr->contentType == CRYPT_CONTENT_DATA )
/* See the long comment for CRYPT_ENVINFO_CONTENTTYPE */
return( CRYPT_ARGERROR_VALUE );
usage = ACTION_SIGN;
break;
case CRYPT_ENVINFO_SIGNATURE_EXTRADATA:
if( envelopeInfoPtr->type != CRYPT_FORMAT_CMS && \
envelopeInfoPtr->type != CRYPT_FORMAT_SMIME )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -