📄 cryptenv.c
字号:
/* If we're querying something which 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( CRYPT_ERROR_NOTFOUND );
envelopeInfoPtr->contentListCurrent = envelopeInfoPtr->contentList;
}
/* 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( CRYPT_ERROR_NOTFOUND );
if( envelopeInfoPtr->iDecryptionKeyset == CRYPT_ERROR )
{
setErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_KEYSET_DECRYPT,
CRYPT_ERRTYPE_ATTR_ABSENT );
return( CRYPT_ERROR_NOTINITED );
}
/* 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,
RESOURCE_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 )
{
RESOURCE_MESSAGE_CHECK_TYPE checkType = RESOURCE_MESSAGE_CHECK_NONE;
OBJECT_TYPE objectType = OBJECT_TYPE_CONTEXT;
ACTION_TYPE usage = ACTION_NONE;
const int value = *( int * ) messageDataPtr;
int 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 );
}
/* In general we can't add new enveloping information once we've started
processing data */
if( messageValue != CRYPT_ENVINFO_CURRENT_COMPONENT && \
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 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
which don't work for PGP */
if( ( envelopeInfoPtr->type == CRYPT_FORMAT_PGP ) && \
( messageValue == CRYPT_ENVINFO_MAC || \
messageValue == CRYPT_ENVINFO_KEY || \
messageValue == CRYPT_ENVINFO_SESSIONKEY || \
messageValue == CRYPT_ENVINFO_HASH ) )
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 */
switch( messageValue )
{
case CRYPT_ENVINFO_DATASIZE:
if( envelopeInfoPtr->payloadSize != CRYPT_UNUSED )
return( CRYPT_ERROR_INITED );
break;
#ifndef NO_COMPRESSION
case CRYPT_ENVINFO_COMPRESSION:
if( envelopeInfoPtr->usage != ACTION_NONE )
return( CRYPT_ERROR_INITED );
usage = ACTION_COMPRESS;
break;
#endif /* NO_COMPRESSION */
case CRYPT_ENVINFO_CONTENTTYPE:
if( envelopeInfoPtr->type == CRYPT_FORMAT_SMIME )
return( CRYPT_ARGERROR_VALUE );
/* 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 which only allow signed messages
through infeasible unless the gateway holds everyone's private
key in able 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( CRYPT_ERROR_INITED );
break;
case CRYPT_ENVINFO_DETACHEDSIGNATURE:
case CRYPT_IATTRIBUTE_INCLUDESIGCERT:
if( envelopeInfoPtr->usage != ACTION_NONE && \
envelopeInfoPtr->usage != ACTION_SIGN )
return( CRYPT_ERROR_INITED );
usage = ACTION_SIGN;
break;
case CRYPT_ENVINFO_MAC:
if( envelopeInfoPtr->usage != ACTION_NONE && \
envelopeInfoPtr->usage != ACTION_MAC )
return( CRYPT_ERROR_INITED );
usage = ACTION_MAC;
break;
case CRYPT_ENVINFO_CURRENT_COMPONENT:
break;
case CRYPT_ENVINFO_KEY:
checkType = RESOURCE_MESSAGE_CHECK_CRYPT;
if( envelopeInfoPtr->usage != ACTION_NONE && \
envelopeInfoPtr->usage != ACTION_CRYPT )
return( CRYPT_ERROR_INITED );
usage = ACTION_CRYPT;
break;
case CRYPT_ENVINFO_SESSIONKEY:
checkType = RESOURCE_MESSAGE_CHECK_CRYPT;
if( !( envelopeInfoPtr->usage == ACTION_NONE || \
( ( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) && \
envelopeInfoPtr->usage == ACTION_CRYPT ) ) )
return( CRYPT_ERROR_INITED );
usage = ACTION_CRYPT;
break;
case CRYPT_ENVINFO_SIGNATURE:
checkType = \
( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) ? \
RESOURCE_MESSAGE_CHECK_PKC_SIGCHECK : \
RESOURCE_MESSAGE_CHECK_PKC_SIGN;
if( envelopeInfoPtr->usage != ACTION_NONE && \
envelopeInfoPtr->usage != ACTION_SIGN )
return( CRYPT_ERROR_INITED );
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 )
return( CRYPT_ARGERROR_VALUE );
else
if( envelopeInfoPtr->usage != ACTION_SIGN )
return( CRYPT_ERROR_NOTINITED );
break;
case CRYPT_ENVINFO_PUBLICKEY:
checkType = RESOURCE_MESSAGE_CHECK_PKC_ENCRYPT;
if( envelopeInfoPtr->usage != ACTION_NONE && \
envelopeInfoPtr->usage != ACTION_CRYPT )
return( CRYPT_ERROR_INITED );
usage = ACTION_CRYPT;
break;
case CRYPT_ENVINFO_PRIVATEKEY:
checkType = RESOURCE_MESSAGE_CHECK_PKC_DECRYPT;
if( envelopeInfoPtr->usage != ACTION_NONE && \
envelopeInfoPtr->usage != ACTION_CRYPT )
return( CRYPT_ERROR_INITED );
usage = ACTION_CRYPT;
break;
case CRYPT_ENVINFO_ORIGINATOR:
checkType = RESOURCE_MESSAGE_CHECK_PKC_KA_EXPORT;
if( envelopeInfoPtr->usage != ACTION_NONE && \
envelopeInfoPtr->usage != ACTION_CRYPT )
return( CRYPT_ERROR_INITED );
usage = ACTION_CRYPT;
if( envelopeInfoPtr->iOriginatorChain != CRYPT_ERROR )
return( CRYPT_ERROR_INITED );
break;
case CRYPT_ENVINFO_HASH:
checkType = RESOURCE_MESSAGE_CHECK_HASH;
if( envelopeInfoPtr->usage != ACTION_NONE && \
envelopeInfoPtr->usage != ACTION_SIGN )
return( CRYPT_ERROR_INITED );
usage = ACTION_SIGN;
break;
case CRYPT_ENVINFO_KEYSET_ENCRYPT:
checkType = RESOURCE_MESSAGE_CHECK_PKC_ENCRYPT;
objectType = OBJECT_TYPE_KEYSET;
if( envelopeInfoPtr->iEncryptionKeyset != CRYPT_ERROR )
return( CRYPT_ERROR_INITED );
break;
case CRYPT_ENVINFO_KEYSET_DECRYPT:
checkType = RESOURCE_MESSAGE_CHECK_PKC_DECRYPT;
objectType = OBJECT_TYPE_KEYSET;
if( envelopeInfoPtr->iDecryptionKeyset != CRYPT_ERROR )
return( CRYPT_ERROR_INITED );
break;
case CRYPT_ENVINFO_KEYSET_SIGCHECK:
checkType = RESOURCE_MESSAGE_CHECK_PKC_SIGCHECK;
objectType = OBJECT_TYPE_KEYSET;
if( envelopeInfoPtr->iSigCheckKeyset != CRYPT_ERROR )
return( CRYPT_ERROR_INITED );
break;
default:
assert( NOTREACHED );
}
if( checkType != RESOURCE_MESSAGE_CHECK_NONE )
{
int type, status;
/* Check the object as appropriate. A key agreement key can also act
as a public key because of the way KEA works, so if a check for a
straight public key fails we try again to see if it's a key
agreement key with import capabilities */
status = krnlSendMessage( value, RESOURCE_IMESSAGE_CHECK, NULL,
checkType );
if( status == CRYPT_ARGERROR_OBJECT && \
messageValue == CRYPT_ENVINFO_PUBLICKEY )
status = krnlSendMessage( value, RESOURCE_IMESSAGE_CHECK, NULL,
RESOURCE_MESSAGE_CHECK_PKC_KA_IMPORT );
if( cryptStatusError( status ) )
return( CRYPT_ARGERROR_NUM1 );
/* Make sure the object corresponds to a representable algorithm
type */
if( checkType == RESOURCE_MESSAGE_CHECK_CRYPT ||
checkType == RESOURCE_MESSAGE_CHECK_HASH )
{
CRYPT_ALGO algorithm;
krnlSendMessage( value, RESOURCE_IMESSAGE_GETATTRIBUTE, &algorithm,
CRYPT_CTXINFO_ALGO );
if( checkType == RESOURCE_MESSAGE_CHECK_CRYPT )
{
CRYPT_MODE mode;
krnlSendMessage( value, RESOURCE_IMESSAGE_GETATTRIBUTE, &mode,
CRYPT_CTXINFO_MODE );
status = envelopeInfoPtr->checkCryptAlgo( algorithm, mode );
}
else
status = envelopeInfoPtr->checkHashAlgo( algorithm );
if( cryptStatusError( status ) )
return( CRYPT_ERROR_NOTAVAIL );
}
/* Make sure the object is of the correct type */
status = krnlSendMessage( value, RESOURCE_IMESSAGE_GETATTRIBUTE,
&type, CRYPT_IATTRIBUTE_TYPE );
if( cryptStatusError( status ) )
return( status );
if( messageValue == CRYPT_ENVINFO_SIGNATURE || \
messageValue == CRYPT_ENVINFO_PUBLICKEY || \
messageValue == CRYPT_ENVINFO_PRIVATEKEY || \
messageValue == CRYPT_ENVINFO_ORIGINATOR )
{
/* Public-key objects can be encryption contexts or certificates */
if( type != objectType && type != OBJECT_TYPE_CERTIFICATE )
return( CRYPT_ARGERROR_NUM1 );
/* If we're using CMS enveloping, the object must have an
initialised cert of the correct type associated with it */
if( envelopeInfoPtr->type == CRYPT_FORMAT_CMS || \
envelopeInfoPtr->type == CRYPT_FORMAT_SMIME )
{
int inited, certType;
status = krnlSendMessage( value, RESOURCE_IMESSAGE_GETATTRIBUTE,
&inited, CRYPT_CERTINFO_IMMUTABLE );
if( cryptStatusError( status ) || !inited )
return( CRYPT_ARGERROR_NUM1 );
status = krnlSendMessage( value, RESOURCE_IMESSAGE_GETATTRIBUTE,
&certType, CRYPT_CERTINFO_CERTTYPE );
if( cryptStatusError( status ) ||
( certType != CRYPT_CERTTYPE_CERTIFICATE && \
certType != CRYPT_CERTTYPE_CERTCHAIN ) )
return( CRYPT_ARGERROR_NUM1 );
}
}
else
if( type != objectType && \
( objectType == OBJECT_TYPE_KEYSET && \
type != OBJECT_TYPE_DEVICE ) )
return( CRYPT_ARGERROR_NUM1 );
}
else
/* If it's additional signature information, make sure the object is
CMS attributes */
if( messageValue == CRYPT_ENVINFO_SIGNATURE_EXTRADATA )
{
int certType, status;
status = krnlSendMessage( value, RESOURCE_IMESSAGE_GETATTRIBUTE,
&certType, CRYPT_CERTINFO_CERTTYPE );
if( cryptStatusError( status ) ||
certType != CRYPT_CERTTYPE_CMS_ATTRIBUTES )
return( CRYPT_ARGERROR_NUM1 );
}
/* If it's meta-information, process it now */
if( messageValue == CRYPT_ENVINFO_CURRENT_COMPONENT )
return( moveCursor( envelopeInfoPtr, value ) );
/* Add it to the envelope */
status = envelopeInfoPtr->addInfo( envelopeInfoPtr, messageValue,
&value, 0 );
if( cryptStatusOK( status ) && usage != ACTION_NONE )
/* The action was successfully added, update the usage if
necessary */
envelopeInfoPtr->usage = usage;
return( status );
}
static int processSetAttributeS( ENVELOPE_INFO *envelopeInfoPtr,
void *messageDataPtr, const int messageValue )
{
RESOURCE_DATA *msgData = ( RESOURCE_DATA * ) messageDataPtr;
MESSAGE_KEYMGMT_INFO getkeyInfo;
ACTION_TYPE usage = ACTION_NONE;
int status;
/* Handle the various information types */
switch( messageValue )
{
case CRYPT_ENVINFO_PASSWORD:
/* Set the envelope usage type based on the fact that we've been
fed a password */
if( envelopeInfoPtr->usage == ACTION_NONE )
usage = ACTION_CRYPT;
else
if( envelopeInfoPtr->usage != ACTION_CRYPT && \
envelopeInfoPtr->usage != ACTION_MAC )
return( CRYPT_ERROR_INITED );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -