📄 pgp.c
字号:
status = readKeyring( keysetInfo, &keyMatchInfo, &keyInfo );
if( cryptStatusError( status ) )
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 ],
CRYPT_MAX_TEXTSIZE );
*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 )
{
static const int cryptMode = CRYPT_MODE_CFB;
/* If no password is supplied, let the caller know that they need a
password */
if( auxInfo == NULL )
return( CRYPT_ERROR_WRONGKEY );
/* 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() */
if( keyInfo->cryptAlgo == CRYPT_ALGO_NONE )
return( CRYPT_ERROR_WRONGKEY );
/* Convert the user password into an encryption context */
setMessageCreateObjectInfo( &createInfo, keyInfo->cryptAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_CONTEXT );
if( cryptStatusError( status ) )
return( status );
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE,
( void * ) &cryptMode, CRYPT_CTXINFO_MODE );
if( cryptStatusOK( status ) )
status = pgpPasswordToKey( createInfo.cryptHandle,
( keyInfo->cryptAlgo == CRYPT_ALGO_AES && \
keyInfo->aesKeySize > 0 ) ? \
keyInfo->aesKeySize : CRYPT_UNUSED,
auxInfo, *auxInfoLength,
keyInfo->hashAlgo, keyInfo->saltSize ? \
keyInfo->salt : NULL,
keyInfo->keySetupIterations );
if( cryptStatusOK( status ) )
{
int ivSize;
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_GETATTRIBUTE, &ivSize,
CRYPT_CTXINFO_IVSIZE );
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, keyInfo->iv, ivSize );
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_IV );
}
}
if( cryptStatusError( status ) )
{
krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
return( status );
}
iSessionKey = createInfo.cryptHandle;
}
/* 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( iSessionKey, IMESSAGE_DECREFCOUNT );
return( status );
}
if( itemType == KEYMGMT_ITEM_PRIVATEKEY )
{
setMessageData( &msgData, pgpInfo->userID[ 0 ],
pgpInfo->userIDlen[ 0 ] );
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_LABEL );
}
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, keyInfo->openPGPkeyID, PGP_KEYID_SIZE );
krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_KEYID_OPENPGP );
}
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, keyInfo->pubKeyData,
keyInfo->pubKeyDataLen );
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE_S, &msgData,
( itemType == KEYMGMT_ITEM_PRIVATEKEY ) ? \
CRYPT_IATTRIBUTE_KEY_PGP_PARTIAL : \
CRYPT_IATTRIBUTE_KEY_PGP );
}
if( cryptStatusError( status ) )
{
krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
return( status );
}
*iCryptHandle = createInfo.cryptHandle;
/* If it's a public key, we're done */
if( itemType != KEYMGMT_ITEM_PRIVATEKEY )
return( CRYPT_OK );
/* Import the encrypted key into the PKC context */
setMechanismWrapInfo( &mechanismInfo, keyInfo->privKeyData,
keyInfo->privKeyDataLen, NULL, 0, *iCryptHandle,
iSessionKey, CRYPT_UNUSED );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_IMPORT,
&mechanismInfo, pgpInfo->isOpenPGP ? \
MECHANISM_PRIVATEKEYWRAP_OPENPGP : \
MECHANISM_PRIVATEKEYWRAP_PGP );
clearMechanismInfo( &mechanismInfo );
krnlSendNotifier( iSessionKey, IMESSAGE_DECREFCOUNT );
return( status );
}
/****************************************************************************
* *
* Write a Key *
* *
****************************************************************************/
/* Add an item to the PGP keyring */
static int setItemFunction( KEYSET_INFO *keysetInfo,
const CRYPT_HANDLE cryptHandle,
const KEYMGMT_ITEM_TYPE itemType,
const char *password, const int passwordLength,
const int flags )
{
CRYPT_ALGO_TYPE cryptAlgo;
PGP_INFO *pgpInfoPtr;
RESOURCE_DATA msgData;
BYTE iD[ CRYPT_MAX_HASHSIZE ];
BOOLEAN contextPresent;
char label[ CRYPT_MAX_TEXTSIZE + 1 ];
int iDsize, i, status;
assert( itemType == KEYMGMT_ITEM_PUBLICKEY || \
itemType == KEYMGMT_ITEM_PRIVATEKEY );
/* Check the object and extract ID information from it */
status = krnlSendMessage( cryptHandle, IMESSAGE_CHECK, NULL,
MESSAGE_CHECK_PKC );
if( cryptStatusOK( status ) )
{
status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE,
&cryptAlgo, CRYPT_CTXINFO_ALGO );
if( cryptStatusOK( status ) && cryptAlgo != CRYPT_ALGO_RSA )
/* For now we can only store RSA keys because of the peculiar
properties of PGP DLP keys, which are actually two keys
with entirely different semantics and attributes but are
nevertheless occasionally treated as a single key by PGP */
status = CRYPT_ARGERROR_NUM1;
}
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, iD, CRYPT_MAX_HASHSIZE );
status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_KEYID );
iDsize = msgData.length;
}
if( cryptStatusError( status ) )
return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
CRYPT_ARGERROR_NUM1 : status );
contextPresent = cryptStatusOK( krnlSendMessage( cryptHandle,
IMESSAGE_CHECK, NULL,
MESSAGE_CHECK_PKC_PRIVATE ) ) ? TRUE : FALSE;
/* Find out where we can add data and what needs to be added. At the
moment we only allow atomic adds since the semantics of PGPs dual keys,
with assorted optional attributes attached to one or both keys, can't
easily be handled using a straightforward add */
pgpInfoPtr = findEntry( keysetInfo->keyData, CRYPT_IKEYID_KEYID, iD,
iDsize, KEYMGMT_FLAG_NONE, NULL );
if( pgpInfoPtr != NULL )
return( CRYPT_ERROR_DUPLICATE );
/* Make sure that the label of what we're adding doesn't duplicate the
label of an existing object */
setMessageData( &msgData, label, CRYPT_MAX_TEXTSIZE );
status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_CTXINFO_LABEL );
if( cryptStatusError( status ) )
return( status );
if( findEntry( keysetInfo->keyData, CRYPT_KEYID_NAME, msgData.data,
msgData.length, KEYMGMT_FLAG_NONE, NULL ) != NULL )
return( CRYPT_ERROR_DUPLICATE );
/* Find out where we can add the new key data */
pgpInfoPtr = keysetInfo->keyData;
for( i = 0; i < MAX_PGP_OBJECTS; i++ )
if( pgpInfoPtr[ i ].keyData == NULL )
break;
if( i == MAX_PGP_OBJECTS )
return( CRYPT_ERROR_OVERFLOW );
pgpInfoPtr = &pgpInfoPtr[ i ];
/* If we're adding a private key, make sure that there's a password
present. Conversely, if there's a password present make sure that
we're adding a private key */
if( contextPresent )
{
/* We're adding a cert, there can't be a password present */
if( password != NULL )
return( CRYPT_ARGERROR_NUM1 );
}
else
/* We're adding a private key, there must be a password present */
if( password == NULL )
return( CRYPT_ARGERROR_STR1 );
/* We're ready to go, lock the object for our exclusive use */
status = krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_LOCKED );
if( cryptStatusError( status ) )
return( status );
/* Not implemented yet */
status = CRYPT_ERROR_NOTAVAIL;
krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_FALSE,
CRYPT_IATTRIBUTE_LOCKED );
return( status );
}
/****************************************************************************
* *
* Init/Shutdown Functions *
* *
****************************************************************************/
/* Shutdown functions */
static void shutdownFunction( KEYSET_INFO *keysetInfo )
{
if( keysetInfo->keyData != NULL )
{
PGP_INFO *pgpInfo = ( PGP_INFO * ) keysetInfo->keyData;
if( keysetInfo->subType == KEYSET_SUBTYPE_PGP_PRIVATE )
{
int i;
for( i = 0; i < MAX_PGP_OBJECTS; i++ )
pgpFreeEntry( &pgpInfo[ i ] );
}
else
pgpFreeEntry( pgpInfo );
clFree( "shutdownFunction", pgpInfo );
keysetInfo->keyData = NULL;
keysetInfo->keyDataSize = 0;
}
}
/* PGP public keyrings can be arbitrarily large so we don't try to do any
preprocessing, all we do at this point is allocate the key info */
static int initPublicFunction( KEYSET_INFO *keysetInfo, const char *name,
const CRYPT_KEYOPT_TYPE options )
{
PGP_INFO *pgpInfo;
assert( name == NULL );
/* Allocate memory for the key info */
if( ( pgpInfo = clAlloc( "initPublicFunction", \
sizeof( PGP_INFO ) ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
memset( pgpInfo, 0, sizeof( PGP_INFO ) );
if( ( pgpInfo->keyData = clAlloc( "initPublicFunction", \
KEYRING_BUFSIZE ) ) == NULL )
{
clFree( "initPublicFunction", pgpInfo );
return( CRYPT_ERROR_MEMORY );
}
pgpInfo->keyDataLen = KEYRING_BUFSIZE;
keysetInfo->keyData = pgpInfo;
keysetInfo->keyDataSize = sizeof( PGP_INFO );
return( CRYPT_OK );
}
/* A PGP private keyring can contain multiple keys and whatnot, so when we
open it we scan it and record various pieces of information about it
that we can use later when we need to access it */
static int initPrivateFunction( KEYSET_INFO *keysetInfo, const char *name,
const CRYPT_KEYOPT_TYPE options )
{
PGP_INFO *pgpInfo;
assert( name == NULL );
/* Allocate the PGP object info */
if( ( pgpInfo = clAlloc( "initPrivateFunction", \
sizeof( PGP_INFO ) * MAX_PGP_OBJECTS ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
memset( pgpInfo, 0, sizeof( PGP_INFO ) * MAX_PGP_OBJECTS );
keysetInfo->keyData = pgpInfo;
keysetInfo->keyDataSize = sizeof( PGP_INFO ) * MAX_PGP_OBJECTS;
/* If this is a newly-created keyset, there's nothing left to do */
if( options == CRYPT_KEYOPT_CREATE )
return( CRYPT_OK );
/* Read all of the keys in the keyring */
return( readKeyring( keysetInfo, NULL, NULL ) );
}
/****************************************************************************
* *
* Keyset Access Routines *
* *
****************************************************************************/
int setAccessMethodPGPPublic( KEYSET_INFO *keysetInfo )
{
/* Set the access method pointers */
keysetInfo->initFunction = initPublicFunction;
keysetInfo->shutdownFunction = shutdownFunction;
keysetInfo->getItemFunction = getItemFunction;
keysetInfo->setItemFunction = setItemFunction;
return( CRYPT_OK );
}
int setAccessMethodPGPPrivate( KEYSET_INFO *keysetInfo )
{
/* Set the access method pointers */
keysetInfo->initFunction = initPrivateFunction;
keysetInfo->shutdownFunction = shutdownFunction;
keysetInfo->getItemFunction = getItemFunction;
keysetInfo->setItemFunction = setItemFunction;
return( CRYPT_OK );
}
#endif /* USE_PGPKEYS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -