📄 cryptenv.c
字号:
NULL, 0, KEYMGMT_FLAG_NONE );
}
status = krnlSendMessage( envelopeInfoPtr->iDecryptionKeyset,
IMESSAGE_KEY_GETKEY, &getkeyInfo,
KEYMGMT_ITEM_PRIVATEKEY );
/* If we managed to get the private key (either bcause it wasn't
protected by a password if it's in a keyset or because it came
from a device), push it into the envelope. If the call
succeeds, this will import the session key and delete the
required-information list */
if( cryptStatusOK( status ) )
{
status = envelopeInfoPtr->addInfo( envelopeInfoPtr,
CRYPT_ENVINFO_PRIVATEKEY,
&getkeyInfo.cryptHandle, 0 );
krnlSendNotifier( getkeyInfo.cryptHandle,
IMESSAGE_DECREFCOUNT );
}
/* If we got the key, there's nothing else needed. If we didn't,
we still return an OK status since the caller is asking us for
the resource which is required and not the status of any
background operation that was performed while trying to obtain
it */
*valuePtr = cryptStatusError( status ) ? \
envelopeInfoPtr->contentListCurrent->envInfo : \
CRYPT_ATTRIBUTE_NONE;
return( CRYPT_OK );
}
case CRYPT_ENVINFO_CONTENTTYPE:
if( envelopeInfoPtr->contentType == CRYPT_CONTENT_NONE )
return( exitErrorNotFound( envelopeInfoPtr,
CRYPT_ENVINFO_CONTENTTYPE ) );
*valuePtr = envelopeInfoPtr->contentType;
return( CRYPT_OK );
case CRYPT_ENVINFO_DETACHEDSIGNATURE:
/* If this isn't signed data or we haven't sorted out the content
details yet, we don't know whether it's a detached sig or
not */
if( envelopeInfoPtr->usage != ACTION_SIGN || \
envelopeInfoPtr->contentType == CRYPT_CONTENT_NONE )
return( exitErrorNotFound( envelopeInfoPtr,
CRYPT_ENVINFO_DETACHEDSIGNATURE ) );
*valuePtr = ( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG ) ? \
TRUE : FALSE;
return( CRYPT_OK );
case CRYPT_ENVINFO_SIGNATURE_RESULT:
{
CRYPT_HANDLE iCryptHandle;
CONTENT_LIST *contentListItem = \
envelopeInfoPtr->contentListCurrent;
const CONTENT_SIG_INFO *sigInfo = &contentListItem->clSigInfo;
MESSAGE_KEYMGMT_INFO getkeyInfo;
assert( contentListItem != NULL );
/* Make sure that the content list item is of the appropriate
type, and if we've already done this one don't process it a
second time. This check is also performed by the addInfo()
code, but we duplicate it here (just for the signature-result
attribute) to avoid having to do an unnecessary key fetch for
non-CMS signatures */
if( contentListItem->envInfo != CRYPT_ENVINFO_SIGNATURE )
return( exitErrorNotFound( envelopeInfoPtr,
CRYPT_ENVINFO_SIGNATURE_RESULT ) );
if( contentListItem->flags & CONTENTLIST_PROCESSED )
{
*valuePtr = sigInfo->processingResult;
return( CRYPT_OK );
}
/* If there's an encoded cert chain present and it hasn't been
instantiated as a cert object yet, instantiate it now. We
don't check the return value since a failure isn't fatal, we
can still perform the sig.check with a key pulled from a
keyset */
if( sigInfo->iSigCheckKey == CRYPT_ERROR && \
envelopeInfoPtr->auxBuffer != NULL )
instantiateCertChain( envelopeInfoPtr, contentListItem );
/* If we have a key instantiated from a cert chain, use that to
check the signature. In theory we could also be re-using the
key from an earlier, not-completed check, however this is only
retained if the check succeeds (to allow a different key to be
tried if the check fails), so in practice this never occurs */
if( sigInfo->iSigCheckKey != CRYPT_ERROR )
{
*valuePtr = envelopeInfoPtr->addInfo( envelopeInfoPtr,
CRYPT_ENVINFO_SIGNATURE,
&sigInfo->iSigCheckKey, TRUE );
return( CRYPT_OK );
}
/* We don't have a sig.check key available (for example from a
CMS cert chain), make sure that there's a keyset available to
pull the key from and get the key from it */
if( envelopeInfoPtr->iSigCheckKeyset == CRYPT_ERROR )
return( exitErrorNotInited( envelopeInfoPtr,
CRYPT_ENVINFO_KEYSET_SIGCHECK ) );
/* Try and get the key. 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, NULL, 0,
KEYMGMT_FLAG_NONE );
}
else
{
setMessageKeymgmtInfo( &getkeyInfo,
CRYPT_IKEYID_ISSUERANDSERIALNUMBER,
contentListItem->issuerAndSerialNumber,
contentListItem->issuerAndSerialNumberSize,
NULL, 0, KEYMGMT_FLAG_NONE );
}
status = krnlSendMessage( envelopeInfoPtr->iSigCheckKeyset,
IMESSAGE_KEY_GETKEY, &getkeyInfo,
KEYMGMT_ITEM_PUBLICKEY );
if( cryptStatusError( status ) )
return( status );
iCryptHandle = getkeyInfo.cryptHandle;
/* Push the public key into the envelope, which performs the
signature check. Adding the key increments its reference
count since the key is usually user-supplied and we need to
keep a reference for use by the envelope, however since the
key we're using here is an internal-use-only key we don't
want to do this so we decrement it again after it's been
added */
*valuePtr = envelopeInfoPtr->addInfo( envelopeInfoPtr,
CRYPT_ENVINFO_SIGNATURE, &iCryptHandle, TRUE );
krnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );
/* If the key wasn't used for the sig check (i.e. it wasn't
stored in the content list for later use, which means it isn't
needed any more), discard it */
if( sigInfo->iSigCheckKey == CRYPT_ERROR )
krnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );
return( CRYPT_OK );
}
case CRYPT_ENVINFO_SIGNATURE:
{
CONTENT_LIST *contentListItem = \
envelopeInfoPtr->contentListCurrent;
CONTENT_SIG_INFO *sigInfo = &contentListItem->clSigInfo;
MESSAGE_CREATEOBJECT_INFO createInfo;
RESOURCE_DATA msgData;
BYTE certData[ 2048 ], *certDataPtr = certData;
assert( contentListItem != NULL );
/* If there's no signing key present, try and instantiate it
from an attached cert chain */
if( sigInfo->iSigCheckKey == CRYPT_ERROR )
{
if( envelopeInfoPtr->auxBuffer == NULL )
/* There's no attached cert chain to recover the signing
key from, we can't go any further */
return( exitErrorNotFound( envelopeInfoPtr,
CRYPT_ENVINFO_SIGNATURE ) );
status = instantiateCertChain( envelopeInfoPtr,
contentListItem );
if( cryptStatusError( status ) )
return( exitError( envelopeInfoPtr,
CRYPT_ENVINFO_SIGNATURE,
CRYPT_ERRTYPE_ATTR_VALUE, status ) );
}
/* If we instantiated the sig-check key ourselves (either from a
keyset or from envelope data) rather than having it supplied
externally, we're done */
if( !( contentListItem->flags & CONTENTLIST_EXTERNALKEY ) )
{
krnlSendNotifier( sigInfo->iSigCheckKey,
IMESSAGE_INCREFCOUNT );
*valuePtr = sigInfo->iSigCheckKey;
return( CRYPT_OK );
}
/* The sig check key was externally supplied by the caller. If
they added a private key+cert combination as the sig.check
key then this will return a supposed signature-check cert
that actually has private-key capabilities. Even adding a
simple cert (+public key context for the sig.check) can be
dangerous since it can act as a subliminal channel if it's
passed on to a different user (although exactly how this would
be exploitable is another question entirely). To avoid this
problem, we completely isolate the added sig.check key by
exporting it and re-importing it as a new certificate object */
setMessageData( &msgData, certDataPtr, 2048 );
status = krnlSendMessage( sigInfo->iSigCheckKey,
IMESSAGE_CRT_EXPORT, &msgData,
CRYPT_CERTFORMAT_CERTCHAIN );
if( status == CRYPT_ERROR_OVERFLOW )
{
if( ( certDataPtr = clAlloc( "processGetAttribute", \
msgData.length ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
setMessageData( &msgData, certDataPtr, msgData.length );
status = krnlSendMessage( sigInfo->iSigCheckKey,
IMESSAGE_CRT_EXPORT, &msgData,
CRYPT_CERTFORMAT_CERTCHAIN );
}
if( cryptStatusOK( status ) )
{
setMessageCreateObjectIndirectInfo( &createInfo, certDataPtr,
msgData.length,
CRYPT_CERTTYPE_CERTCHAIN );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
&createInfo, OBJECT_TYPE_CERTIFICATE );
}
if( certDataPtr != certData )
clFree( "processGetAttribute", certDataPtr );
if( cryptStatusError( status ) )
return( exitError( envelopeInfoPtr,
CRYPT_ENVINFO_SIGNATURE,
CRYPT_ERRTYPE_ATTR_VALUE,
status ) );
/* We've created a new instantiation of the sig.check key which
is distinct from the externally-supplied original, return it
to the caller */
krnlSendNotifier( sigInfo->iSigCheckKey, IMESSAGE_DECREFCOUNT );
*valuePtr = sigInfo->iSigCheckKey = createInfo.cryptHandle;
return( CRYPT_OK );
}
case CRYPT_ENVINFO_SIGNATURE_EXTRADATA:
{
CRYPT_HANDLE iCryptHandle;
CONTENT_LIST *contentListItem = \
envelopeInfoPtr->contentListCurrent;
assert( contentListItem != NULL );
/* Make sure that there's extra data present */
iCryptHandle = contentListItem->clSigInfo.iExtraData;
if( iCryptHandle == CRYPT_ERROR )
return( exitErrorNotFound( envelopeInfoPtr,
CRYPT_ENVINFO_SIGNATURE_EXTRADATA ) );
/* Return it to the caller */
krnlSendNotifier( iCryptHandle, IMESSAGE_INCREFCOUNT );
*valuePtr = iCryptHandle;
return( CRYPT_OK );
}
#if 0 /* Unused, removed 9/9/03 */
case CRYPT_IATTRIBUTE_PAYLOADSIZE:
/* This is an internal attribute used by high-level cryptlib
functions that use CMS as their native data format. These
typically push the entire data quantity into an envelope
at once and then need to know how much data will be produced
to write to an output stream */
*valuePtr = envelopeInfoPtr->bufPos;
return( CRYPT_OK );
#endif /* 0 */
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;
}
/* 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 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -