pgp.c
来自「cryptlib安全工具包」· C语言 代码 · 共 915 行 · 第 1/3 页
C
915 行
return( FALSE );
}
/* Locate a key based on an ID. This is complicated somewhat by the fact
that PGP groups multiple keys around the same textual ID so we have to
check both keys and subkeys for a possible match */
CHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1, 4 ) ) \
static PGP_INFO *findEntry( const PGP_INFO *pgpInfo,
IN_LENGTH_SHORT const int noPgpObjects,
IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,
IN_BUFFER( keyIDlength ) const void *keyID,
IN_LENGTH_KEYID const int keyIDlength,
IN_FLAGS_Z( KEYMGMT ) const int requestedUsage,
OUT_OPT_PTR PGP_KEYINFO **keyInfo )
{
CONST_INIT_STRUCT_4( KEY_MATCH_INFO keyMatchInfo, \
keyIDtype, keyID, keyIDlength, requestedUsage );
int i;
CONST_SET_STRUCT( keyMatchInfo.keyIDtype = keyIDtype; \
keyMatchInfo.keyID = keyID; \
keyMatchInfo.keyIDlength = keyIDlength; \
keyMatchInfo.flags = requestedUsage );
assert( isReadPtr( pgpInfo, sizeof( PGP_INFO ) ) );
assert( isReadPtr( keyID, keyIDlength ) );
assert( keyInfo == NULL || \
isWritePtr( keyInfo, sizeof( PGP_KEYINFO * ) ) );
REQUIRES_N( noPgpObjects >= 1 && noPgpObjects < MAX_INTLENGTH_SHORT );
REQUIRES_N( keyIDtype == CRYPT_KEYID_NAME || \
keyIDtype == CRYPT_KEYID_URI || \
keyIDtype == CRYPT_IKEYID_KEYID || \
keyIDtype == CRYPT_IKEYID_PGPKEYID );
REQUIRES_N( keyIDlength >= MIN_NAME_LENGTH && \
keyIDlength < MAX_ATTRIBUTE_SIZE );
REQUIRES_N( requestedUsage >= KEYMGMT_FLAG_NONE && \
requestedUsage < KEYMGMT_FLAG_MAX );
REQUIRES_N( ( requestedUsage & KEYMGMT_MASK_USAGEOPTIONS ) != \
KEYMGMT_MASK_USAGEOPTIONS );
/* Clear return value */
if( keyInfo != NULL )
*keyInfo = NULL;
for( i = 0; i < noPgpObjects && i < FAILSAFE_ITERATIONS_MED; i++ )
{
if( pgpCheckKeyMatch( &pgpInfo[ i ], &pgpInfo[ i ].key,
&keyMatchInfo ) )
{
if( keyInfo != NULL )
*keyInfo = ( PGP_KEYINFO * ) &pgpInfo[ i ].key;
return( ( PGP_INFO * ) &pgpInfo[ i ] );
}
if( pgpCheckKeyMatch( &pgpInfo[ i ], &pgpInfo[ i ].subKey,
&keyMatchInfo ) )
{
if( keyInfo != NULL )
*keyInfo = ( PGP_KEYINFO * ) &pgpInfo[ i ].subKey;
return( ( PGP_INFO * ) &pgpInfo[ i ] );
}
}
ENSURES_N( i < FAILSAFE_ITERATIONS_MED );
return( NULL );
}
/****************************************************************************
* *
* Get a Key *
* *
****************************************************************************/
/* Read key data from a PGP keyring */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \
static int getItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,
OUT_HANDLE_OPT CRYPT_HANDLE *iCryptHandle,
IN_ENUM( KEYMGMT_ITEM ) \
const KEYMGMT_ITEM_TYPE itemType,
IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,
IN_BUFFER( keyIDlength ) const void *keyID,
IN_LENGTH_KEYID const int keyIDlength,
IN_OPT void *auxInfo,
INOUT_OPT int *auxInfoLength,
IN_FLAGS_Z( KEYMGMT ) const int flags )
{
CRYPT_CONTEXT iDecryptionKey = DUMMY_INIT, iLocalContext;
PGP_INFO *pgpInfo = ( PGP_INFO * ) keysetInfoPtr->keyData;
PGP_KEYINFO *keyInfo;
MESSAGE_CREATEOBJECT_INFO createInfo;
MECHANISM_WRAP_INFO mechanismInfo;
MESSAGE_DATA msgData;
const int auxInfoMaxLength = *auxInfoLength;
int status;
assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
assert( isWritePtr( iCryptHandle, sizeof( CRYPT_HANDLE ) ) );
assert( isReadPtr( keyID, keyIDlength ) );
assert( ( auxInfo == NULL && auxInfoMaxLength == 0 ) || \
isReadPtr( auxInfo, auxInfoMaxLength ) );
REQUIRES( keysetInfoPtr->type == KEYSET_FILE && \
( keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PUBLIC ||
keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PRIVATE ) );
REQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \
itemType == KEYMGMT_ITEM_PRIVATEKEY );
REQUIRES( keyIDtype == CRYPT_KEYID_NAME || \
keyIDtype == CRYPT_KEYID_URI || \
keyIDtype == CRYPT_IKEYID_KEYID || \
keyIDtype == CRYPT_IKEYID_PGPKEYID );
REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
keyIDlength < MAX_ATTRIBUTE_SIZE );
REQUIRES( ( auxInfo == NULL && *auxInfoLength == 0 ) || \
( auxInfo != NULL && \
*auxInfoLength > 0 && \
*auxInfoLength < MAX_INTLENGTH_SHORT ) );
REQUIRES( flags >= KEYMGMT_FLAG_NONE && flags < KEYMGMT_FLAG_MAX );
/* Find the requested item. This is complicated somewhat by the fact
that private keys are held in memory while public keys (which can
be arbitrarily numerous) are held on disk. This means that the former
(and also public keys read from a private-key keyring) are found with
a quick in-memory search while the latter require a scan of the
keyring on disk */
if( itemType == KEYMGMT_ITEM_PRIVATEKEY || \
keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PRIVATE )
{
/* Try and locate the appropriate object in the PGP collection */
pgpInfo = findEntry( keysetInfoPtr->keyData, MAX_PGP_OBJECTS,
keyIDtype, keyID, keyIDlength, flags,
&keyInfo );
if( pgpInfo == NULL )
return( CRYPT_ERROR_NOTFOUND );
}
else
{
CONST_INIT_STRUCT_4( KEY_MATCH_INFO keyMatchInfo, \
keyIDtype, keyID, keyIDlength, flags );
CONST_SET_STRUCT( keyMatchInfo.keyIDtype = keyIDtype; \
keyMatchInfo.keyID = keyID; \
keyMatchInfo.keyIDlength = keyIDlength; \
keyMatchInfo.flags = flags );
/* Try and find the required key in the file */
sseek( &keysetInfoPtr->keysetFile->stream, 0 );
status = pgpReadKeyring( &keysetInfoPtr->keysetFile->stream,
pgpInfo, 1, &keyMatchInfo, &keyInfo,
KEYSET_ERRINFO );
if( cryptStatusError( status ) && status != OK_SPECIAL )
return( status );
}
/* If it's just a check or label read, we're done */
if( flags & ( KEYMGMT_FLAG_CHECK_ONLY | KEYMGMT_FLAG_LABEL_ONLY ) )
{
if( flags & KEYMGMT_FLAG_LABEL_ONLY )
{
const int userIDsize = min( pgpInfo->userIDlen[ 0 ],
auxInfoMaxLength );
REQUIRES( pgpInfo->userIDlen[ 0 ] > 0 && \
pgpInfo->userIDlen[ 0 ] < MAX_INTLENGTH_SHORT );
*auxInfoLength = userIDsize;
if( auxInfo != NULL )
memcpy( auxInfo, pgpInfo->userID[ 0 ], userIDsize );
}
return( CRYPT_OK );
}
/* Set up the key to decrypt the private-key fields if necessary */
if( itemType == KEYMGMT_ITEM_PRIVATEKEY )
{
/* If no password is supplied let the caller know that they need a
password */
if( auxInfo == NULL )
{
retExt( CRYPT_ERROR_WRONGKEY,
( CRYPT_ERROR_WRONGKEY, KEYSET_ERRINFO,
"Need a password to decrypt the private key" ) );
}
/* If the key is stored as plaintext we can't do anything with it.
This is just a safety check, we never get here anyway, see the
comment in readSecretKeyDecryptionInfo() for details */
if( keyInfo->cryptAlgo == CRYPT_ALGO_NONE )
return( CRYPT_ERROR_WRONGKEY );
/* Create a decryption context to decrypt the private key */
status = createDecryptionContext( &iDecryptionKey, keyInfo,
auxInfo, auxInfoMaxLength );
if( cryptStatusError( status ) )
{
retExt( status,
( status, KEYSET_ERRINFO,
"Couldn't create decryption context for private key "
"from user password" ) );
}
}
/* Load the key into the encryption context */
setMessageCreateObjectInfo( &createInfo, keyInfo->pkcAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_CONTEXT );
if( cryptStatusError( status ) )
{
if( itemType == KEYMGMT_ITEM_PRIVATEKEY )
krnlSendNotifier( iDecryptionKey, IMESSAGE_DECREFCOUNT );
return( status );
}
iLocalContext = createInfo.cryptHandle;
if( itemType == KEYMGMT_ITEM_PRIVATEKEY )
{
REQUIRES( pgpInfo->userIDlen[ 0 ] > 0 && \
pgpInfo->userIDlen[ 0 ] < MAX_INTLENGTH_SHORT );
setMessageData( &msgData, pgpInfo->userID[ 0 ],
min( pgpInfo->userIDlen[ 0 ],
CRYPT_MAX_TEXTSIZE ) );
status = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_CTXINFO_LABEL );
}
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, keyInfo->openPGPkeyID, PGP_KEYID_SIZE );
status = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_KEYID_OPENPGP );
}
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, keyInfo->pubKeyData,
keyInfo->pubKeyDataLen );
status = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE_S,
&msgData,
( itemType == KEYMGMT_ITEM_PRIVATEKEY ) ? \
CRYPT_IATTRIBUTE_KEY_PGP_PARTIAL : \
CRYPT_IATTRIBUTE_KEY_PGP );
}
if( cryptStatusError( status ) )
{
krnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );
retExt( status,
( status, KEYSET_ERRINFO,
"Couldn't recreate key from stored %s key data",
( itemType == KEYMGMT_ITEM_PRIVATEKEY ) ? \
"private" : "public" ) );
}
/* If it's a public key, we're done */
if( itemType != KEYMGMT_ITEM_PRIVATEKEY )
{
*iCryptHandle = iLocalContext;
return( CRYPT_OK );
}
/* Import the encrypted key into the PKC context */
setMechanismWrapInfo( &mechanismInfo, keyInfo->privKeyData,
keyInfo->privKeyDataLen, NULL, 0, iLocalContext,
iDecryptionKey );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_IMPORT,
&mechanismInfo, pgpInfo->isOpenPGP ? \
( keyInfo->hashedChecksum ?
MECHANISM_PRIVATEKEYWRAP_OPENPGP : \
MECHANISM_PRIVATEKEYWRAP_OPENPGP_OLD ) : \
MECHANISM_PRIVATEKEYWRAP_PGP2 );
clearMechanismInfo( &mechanismInfo );
krnlSendNotifier( iDecryptionKey, IMESSAGE_DECREFCOUNT );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );
retExt( status,
( status, KEYSET_ERRINFO,
"Couldn't unwrap private key" ) );
}
*iCryptHandle = iLocalContext;
return( CRYPT_OK );
}
/****************************************************************************
* *
* Add a Key *
* *
****************************************************************************/
/* Add an item to the PGP keyring */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int setItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,
IN_HANDLE const CRYPT_HANDLE cryptHandle,
IN_ENUM( KEYMGMT_ITEM ) \
const KEYMGMT_ITEM_TYPE itemType,
IN_BUFFER_OPT( passwordLength ) const char *password,
IN_LENGTH_NAME_Z const int passwordLength,
IN_FLAGS( KEYMGMT ) const int flags )
{
CRYPT_ALGO_TYPE cryptAlgo;
PGP_INFO *pgpInfo = ( PGP_INFO * ) keysetInfoPtr->keyData, *pgpInfoPtr;
MESSAGE_DATA msgData;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?