📄 pgp.c
字号:
BYTE iD[ CRYPT_MAX_HASHSIZE + 8 ];
BOOLEAN privkeyPresent;
char label[ CRYPT_MAX_TEXTSIZE + 1 + 8 ];
int iDsize = DUMMY_INIT, status;
assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
assert( ( itemType == KEYMGMT_ITEM_PUBLICKEY && \
password == NULL && passwordLength == 0 ) || \
( itemType == KEYMGMT_ITEM_PRIVATEKEY && \
isReadPtr( password, passwordLength ) ) );
REQUIRES( keysetInfoPtr->type == KEYSET_FILE && \
( keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PUBLIC ||
keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PRIVATE ) );
REQUIRES( isHandleRangeValid( cryptHandle ) );
REQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \
itemType == KEYMGMT_ITEM_PRIVATEKEY );
REQUIRES( ( password == NULL && passwordLength == 0 ) || \
( password != NULL && \
passwordLength >= MIN_NAME_LENGTH && \
passwordLength < MAX_ATTRIBUTE_SIZE ) );
REQUIRES( ( itemType == KEYMGMT_ITEM_PUBLICKEY && \
password == NULL && passwordLength == 0 ) || \
( itemType == KEYMGMT_ITEM_PRIVATEKEY && \
password != NULL && passwordLength != 0 ) );
REQUIRES( flags == KEYMGMT_FLAG_NONE );
/* 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 );
if( cryptStatusOK( status ) )
iDsize = msgData.length;
}
if( cryptStatusError( status ) )
{
return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
CRYPT_ARGERROR_NUM1 : status );
}
privkeyPresent = cryptStatusOK( \
krnlSendMessage( cryptHandle, IMESSAGE_CHECK, NULL,
MESSAGE_CHECK_PKC_PRIVATE ) ) ? TRUE : FALSE;
/* If we're adding a private key make sure that there's a context and a
password present. Conversely if we're adding a public key make sure
that there's no password present. The password-check has already
been performed by the kernel but we perform a second check here just
to be safe. The private-key check can't be performed by the kernel
since it doesn't know the difference between public- and private-key
contexts */
switch( itemType )
{
case KEYMGMT_ITEM_PUBLICKEY:
if( password != NULL )
return( CRYPT_ARGERROR_STR1 );
break;
case KEYMGMT_ITEM_PRIVATEKEY:
if( !privkeyPresent )
{
retExtArg( CRYPT_ARGERROR_NUM1,
( CRYPT_ARGERROR_NUM1, KEYSET_ERRINFO,
"Item being added doesn't contain a private "
"key" ) );
}
if( password == NULL )
return( CRYPT_ARGERROR_STR1 );
break;
default:
retIntError();
}
/* 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 PGP's dual
keys, with assorted optional attributes attached to one or both keys
can't easily be handled using a straightforward add */
pgpInfoPtr = findEntry( keysetInfoPtr->keyData, MAX_PGP_OBJECTS,
CRYPT_IKEYID_KEYID, iD, iDsize,
KEYMGMT_FLAG_NONE, NULL );
if( pgpInfoPtr != NULL )
{
retExt( CRYPT_ERROR_DUPLICATE,
( CRYPT_ERROR_DUPLICATE, KEYSET_ERRINFO,
"Item is already present in keyset" ) );
}
/* Make sure that the label of what we're adding doesn't duplicate the
label of an existing object */
if( privkeyPresent )
{
setMessageData( &msgData, label, CRYPT_MAX_TEXTSIZE );
status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_CTXINFO_LABEL );
if( cryptStatusError( status ) )
return( status );
if( findEntry( keysetInfoPtr->keyData, MAX_PGP_OBJECTS,
CRYPT_KEYID_NAME, msgData.data, msgData.length,
KEYMGMT_FLAG_NONE, NULL ) != NULL )
{
retExt( CRYPT_ERROR_DUPLICATE,
( CRYPT_ERROR_DUPLICATE, KEYSET_ERRINFO,
"Item with this label is already present" ) );
}
}
/* Find out where we can add the new key data */
pgpInfoPtr = findFreeEntry( pgpInfo, MAX_PGP_OBJECTS );
if( pgpInfoPtr == NULL )
{
retExt( CRYPT_ERROR_OVERFLOW,
( CRYPT_ERROR_OVERFLOW, KEYSET_ERRINFO,
"No more room in keyset to add this item" ) );
}
/* Not implemented yet */
return( CRYPT_ERROR_NOTAVAIL );
}
/****************************************************************************
* *
* Init/Shutdown Functions *
* *
****************************************************************************/
/* Shutdown functions */
RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int shutdownFunction( INOUT KEYSET_INFO *keysetInfoPtr )
{
PGP_INFO *pgpInfo = ( PGP_INFO * ) keysetInfoPtr->keyData;
assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
REQUIRES( keysetInfoPtr->type == KEYSET_FILE && \
( keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PUBLIC ||
keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PRIVATE ) );
/* If there's no PGP information data cached, we're done */
if( pgpInfo == NULL )
return( CRYPT_OK );
/* Free the cached key information */
if( keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PRIVATE )
{
int i;
for( i = 0; i < MAX_PGP_OBJECTS; i++ )
pgpFreeEntry( &pgpInfo[ i ] );
}
else
pgpFreeEntry( pgpInfo );
clFree( "shutdownFunction", pgpInfo );
keysetInfoPtr->keyData = NULL;
keysetInfoPtr->keyDataSize = 0;
return( CRYPT_OK );
}
/* 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 information */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int initPublicFunction( INOUT KEYSET_INFO *keysetInfoPtr,
STDC_UNUSED const char *name,
STDC_UNUSED const int nameLength,
IN_ENUM( CRYPT_KEYOPT ) \
const CRYPT_KEYOPT_TYPE options )
{
PGP_INFO *pgpInfo;
assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
REQUIRES( keysetInfoPtr->type == KEYSET_FILE && \
keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PUBLIC );
REQUIRES( name == NULL && nameLength == 0 );
REQUIRES( options >= CRYPT_KEYOPT_NONE && options < CRYPT_KEYOPT_LAST );
/* Allocate memory for the key information */
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;
keysetInfoPtr->keyData = pgpInfo;
keysetInfoPtr->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 */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int initPrivateFunction( INOUT KEYSET_INFO *keysetInfoPtr,
STDC_UNUSED const char *name,
STDC_UNUSED const int nameLength,
IN_ENUM( CRYPT_KEYOPT ) \
const CRYPT_KEYOPT_TYPE options )
{
PGP_INFO *pgpInfo;
int status;
assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
REQUIRES( keysetInfoPtr->type == KEYSET_FILE && \
keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PRIVATE );
REQUIRES( name == NULL && nameLength == 0 );
REQUIRES( options >= CRYPT_KEYOPT_NONE && options < CRYPT_KEYOPT_LAST );
/* Allocate the PGP object information */
if( ( pgpInfo = clAlloc( "initPrivateFunction", \
sizeof( PGP_INFO ) * MAX_PGP_OBJECTS ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
memset( pgpInfo, 0, sizeof( PGP_INFO ) * MAX_PGP_OBJECTS );
keysetInfoPtr->keyData = pgpInfo;
keysetInfoPtr->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 */
status = pgpReadKeyring( &keysetInfoPtr->keysetFile->stream, pgpInfo,
MAX_PGP_OBJECTS, NULL, NULL, KEYSET_ERRINFO );
if( status == OK_SPECIAL )
{
/* We couldn't process one or more packets, make the keyset read-
only to ensure that the incomplete key data isn't written to
disk */
keysetInfoPtr->options = CRYPT_KEYOPT_READONLY;
status = CRYPT_OK;
}
if( cryptStatusError( status ) )
keysetInfoPtr->shutdownFunction( keysetInfoPtr );
return( status );
}
/****************************************************************************
* *
* Keyset Access Routines *
* *
****************************************************************************/
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int setAccessMethodPGPPublic( INOUT KEYSET_INFO *keysetInfoPtr )
{
assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
REQUIRES( keysetInfoPtr->type == KEYSET_FILE && \
( keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PUBLIC ||
keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PRIVATE ) );
/* Set the access method pointers */
keysetInfoPtr->initFunction = initPublicFunction;
keysetInfoPtr->shutdownFunction = shutdownFunction;
keysetInfoPtr->getItemFunction = getItemFunction;
keysetInfoPtr->setItemFunction = setItemFunction;
return( CRYPT_OK );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int setAccessMethodPGPPrivate( INOUT KEYSET_INFO *keysetInfoPtr )
{
assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
REQUIRES( keysetInfoPtr->type == KEYSET_FILE && \
( keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PUBLIC ||
keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PRIVATE ) );
/* Set the access method pointers */
keysetInfoPtr->initFunction = initPrivateFunction;
keysetInfoPtr->shutdownFunction = shutdownFunction;
keysetInfoPtr->getItemFunction = getItemFunction;
keysetInfoPtr->setItemFunction = setItemFunction;
return( CRYPT_OK );
}
#endif /* USE_PGPKEYS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -