📄 pgpkeyio.c
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
Input, output (export) functions for keydbs
$Id: pgpKeyIO.c,v 1.72 2002/08/06 20:11:00 dallen Exp $
____________________________________________________________________________*/
#include "pgpConfig.h"
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "pgpContext.h"
#include "pgpKeyPriv.h"
#include "pgpDebug.h"
#include "pgpAnnotate.h"
#include "pgpEncodePriv.h"
#include "pgpEnv.h"
#include "pgpErrors.h"
#include "pgpFileNames.h"
#include "pgpFileRef.h"
#include "pgpFileSpec.h"
#include "pgpPipeline.h"
#include "pgpRandomX9_17.h"
#include "pgpRandomPoolPriv.h"
#include "pgpRndSeed.h"
#include "pgpSigSpec.h"
#include "pgpPubKey.h"
#include "pgpTimeDate.h"
#include "pgpTrustPriv.h"
#include "pgpOptionList.h"
#include "pgpUtilitiesPriv.h"
#include "pgpX509Priv.h"
#if PGP_MACINTOSH
#include "MacStrings.h"
#include "MacFiles.h"
#endif
#define elemsof(x) ((unsigned)(sizeof(x)/sizeof(*x)))
/* See if the newly opened keyring appears to needs sig checking */
static PGPError
sIsSigCheckNeeded( PGPKeyDB *db, PGPBoolean *sigCheckNeeded )
{
PGPBoolean needSigCheck;
PGPKeyDBObj * key;
PGPKeyDBObj * child;
*sigCheckNeeded = FALSE;
needSigCheck = FALSE;
/*
* We look for a key with a revocation signature which has not
* been tried, such that the key's revoke bit is not set. This is
* how some old version of PGP leave revocations. We always set the
* key's revocation bit in the file, so this will not happen with
* keyrings written by this library.
*/
for( key = db->firstKeyInDB; IsntNull(key); key = key->next )
{
if( !pgpKeyDBObjIsReal( key ) )
continue;
for( child = key->down; IsntNull(child); child = child->next )
{
if( !pgpKeyDBObjIsReal( child ) )
continue;
if ( pgpObjectType( child ) == RINGTYPE_SIG &&
pgpSigType( child ) == PGP_SIGTYPE_KEY_REVOKE &&
pgpSigTrust( child ) == PGP_SIGTRUST_UNTRIED )
{
if ( pgpObjectType( key ) == RINGTYPE_KEY &&
!pgpKeyRevoked( key ) )
{
/* Here we have our case we are looking for */
needSigCheck = TRUE;
break;
}
}
}
}
*sigCheckNeeded = needSigCheck;
return kPGPError_NoErr;
}
PGPError
pgpOpenKeyDBFile_internal(
PGPContextRef cdkContext,
PGPOpenKeyDBFileOptions openFlags,
PFLFileSpecRef pubFileRef,
PFLFileSpecRef privFileRef,
PGPKeyDBRef * keyDBOut )
{
PGPKeyDB *db = NULL;
PGPBoolean sigCheckNeeded;
PGPError err;
PFLFileInfo pubFileInfo;
PGPTime curTime, pubModTime;
/*
* Check creation time of pub file so we can check for objects
* expired since then.
*/
err = PFLGetFileInfo( pubFileRef, &pubFileInfo );
if( IsPGPError( err ) )
{
err = kPGPError_NoErr;
pubModTime = 0UL;
} else {
pubModTime = PGPGetPGPTimeFromStdTime( pubFileInfo.modificationTime );
}
db = pgpCreateKeyDBFromKeyRings( cdkContext, pubFileRef, privFileRef,
openFlags, &err );
if( IsPGPError( err ) )
goto error;
/*
* Some earlier versions of PGP don't cache revocation info. We will
* check signatures if the keyring has unchecked revocation signatures
* where the key does not have the revoke flag cached.
*/
if( IsPGPError( err = sIsSigCheckNeeded( db, &sigCheckNeeded ) ) )
goto error;
if( sigCheckNeeded )
{
if ( IsPGPError( err = PGPCheckKeyRingSigs( pgpKeyDBPeekRootSet(db),
NULL, FALSE, NULL, NULL )))
goto error;
if ( IsPGPError( err = PGPCalculateTrust( db->rootSet, NULL ) ) )
goto error;
} else {
/* We will re-run trust propagation if anything has expired */
curTime = PGPGetTime();
if( pgpKeyDBHasExpiringObjects( db, pubModTime, curTime ) ) {
if ( IsPGPError( err = PGPCalculateTrust( db->rootSet, NULL ) ) )
goto error;
}
}
err = kPGPError_NoErr;
error:
if (db != NULL && IsPGPError( err ))
{
PGPFreeKeyDB(db);
db = NULL;
}
*keyDBOut = db;
pgpAssertErrWithPtr( err, *keyDBOut );
return err;
}
/*
* Open the specified keyrings for user, return keyset for it.
*/
PGPError
PGPOpenKeyDBFile(
PGPContextRef cdkContext,
PGPOpenKeyDBFileOptions openFlags,
PGPFileSpecRef pubFileRefIn,
PGPFileSpecRef privFileRefIn,
PGPKeyDBRef * keyDBOut )
{
PFLFileSpecRef pubFileRef = (PFLFileSpecRef)pubFileRefIn;
PFLFileSpecRef privFileRef = (PFLFileSpecRef)privFileRefIn;
PGPUInt32 kdbid;
PGPUInt32 numKeys;
PGPUInt32 * keyArray;
PGPSize keyArraySize;
PGPError err;
PGPValidatePtr( keyDBOut );
*keyDBOut = NULL;
PGPValidateContext( cdkContext );
PFLValidateFileSpec( pubFileRef );
if( IsntNull( privFileRef ) )
PFLValidateFileSpec( privFileRef );
pgpEnterPGPErrorFunction();
/* In production mode, if no server, don't use double data structs */
#if !PGP_FORCEBACKEND
if( !pgpRPCEnabled() )
{
/* Open it locally */
return pgpOpenKeyDBFile_internal( cdkContext, openFlags, pubFileRef,
privFileRef, keyDBOut );
}
#endif
err = pgpOpenKeyDBFile_back( cdkContext, openFlags, pubFileRef,
privFileRef, &kdbid, &numKeys, &keyArray,
&keyArraySize );
if( IsPGPError( err ) )
return err;
err = pgpNewFrontEndKeyDB( cdkContext, kdbid, keyArray, numKeys, keyDBOut);
if( IsntNull( keyArray) )
PGPFreeData( keyArray );
return err;
}
/*
* Add keys to a keydb from a dynamically allocated binary key buffer.
* Makes a copy of the binary key buffer data, so caller can dispose of
* it after this call.
*/
PGPError
pgpImportKeyBinary_internal (
PGPContextRef cdkContext,
const PGPByte *buffer,
size_t length,
PGPKeyDBRef * outRef
)
{
PGPKeyDBRef kdb;
PGPError err = kPGPError_NoErr;
*outRef = NULL;
/* Create a file type KeyDB from the buffer */
kdb = pgpCreateKeyDBFromMemory (cdkContext, buffer, length, &err );
if ( IsNull( kdb ) )
{
pgpAssert( IsPGPError( err ) );
}
*outRef = kdb;
return err;
}
/* This is only called from the front end */
PGPError
pgpImportKeyBinary (
PGPContextRef cdkContext,
PGPByte *buffer,
size_t length,
PGPKeyDBRef * outRef
)
{
PGPUInt32 kdbid;
PGPUInt32 numKeys;
PGPUInt32 * keyArray;
PGPSize keyArraySize;
PGPError err = kPGPError_NoErr;
err = pgpImportKeyBinary_back( cdkContext, buffer, length, &kdbid,
&numKeys, &keyArray, &keyArraySize );
if( IsPGPError( err ) )
return err;
err = pgpNewFrontEndKeyDB( cdkContext, kdbid, keyArray, numKeys, outRef);
if( IsntNull( keyArray) )
PGPFreeData( keyArray );
return err;
}
/* Import an x509 cert from the specified optionlist input */
static PGPError
sImportX509Certificate( PGPContextRef context, PGPKeyDBRef *db,
PGPInputFormat inputFormat, PGPOptionListRef optionList)
{
PGPByte *bufPtr;
PGPSize bufLength;
PGPByte *outBuf=NULL, *certSet=NULL, *crlSet=NULL;
PGPSize outBufLength, certSetLength, crlSetLength;
PGPBoolean mustFreeBuf = FALSE;
PGPKeyDB *db2 = NULL;
char *passphrase;
PGPSize passphraseLength = 0;
PGPKeyDBRef refdb;
PGPError err = kPGPError_NoErr;
pgpAssert(IsntNull( db ) );
*db = NULL;
err = pgpSetupInputToBuffer( context, optionList, &bufPtr, &bufLength,
&mustFreeBuf );
if( IsPGPError( err ) )
goto error;
/* Refdb helps on input */
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_KeyDBRef, FALSE,
"%p", &refdb ) ) )
goto error;
if( inputFormat == kPGPInputFormat_PKCS12 ||
inputFormat == kPGPInputFormat_PrivateKeyInfo )
{
/* Input a private X.509 key */
PGPKeyDBObj *key = NULL;
if( inputFormat == kPGPInputFormat_PKCS12 )
{
/* Pick up optional passphrase */
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_Passphrase, FALSE,
"%p%l", &passphrase, &passphraseLength ) ) )
goto error;
err = PKCS12InputKey( context, bufPtr, bufLength,
(PGPByte *) passphrase, passphraseLength,
&outBuf, &outBufLength,
&certSet, &certSetLength );
if( IsPGPError( err ) )
goto error;
/* Switch input to PKCS-8 data */
if( mustFreeBuf )
PGPFreeData( bufPtr );
bufPtr = outBuf;
bufLength = outBufLength;
mustFreeBuf = TRUE;
}
/* Now have PKCS-8 data in bufPtr/bufLength */
/* Process the returned cert set */
if( IsntNull( certSet ) )
{
err = pgpDecodeX509CertSet( certSet, certSetLength,
context, refdb, db );
if( IsPGPError( err ) )
goto error;
refdb = *db; /* Use just-imported cert as ref */
}
/* Decode PKCS-8 data */
err = pgpDecodePCKS8( bufPtr, bufLength, context, refdb,
IsntNull(*db)?&db2:db );
if( IsPGPError( err ) )
goto error;
/* Combine keysets if necessary */
if( IsntNull( db2 ) )
{
err = PGPCopyKeys( pgpKeyDBPeekRootSet(db2), *db, NULL );
if( IsPGPError( err ) )
goto error;
PGPFreeKeyDB( db2 );
db2 = NULL;
}
/* Set passphrase on newly imported key */
if( passphraseLength != 0 )
{
/* Find key we just imported */
for( key = (*db)->firstKeyInDB; IsntNull(key); key=key->next )
{
if( !pgpKeyDBObjIsReal( key ) )
continue;
if (pgpKeyIsSec( key ) )
break;
}
if( key )
{
err = pgpDoChangePassphrase_internal( *db, key, NULL, NULL, 0,
passphrase, passphraseLength,
FALSE, 0, FALSE );
if( IsPGPError( err ) )
goto error;
}
}
/* Done */
goto error;
}
if( inputFormat >= kPGPInputFormat_PEMEncodedX509Cert &&
inputFormat <= kPGPInputFormat_NetscapeV1_PEMEncoded )
{
/* Need to remove PEM encoding */
PGPByte *tmpBuf;
PGPSize tmpBufLength;
err = pgpRemovePEMEncoding( context, bufPtr, bufLength,
&tmpBuf, &tmpBufLength );
if( IsPGPError( err ) )
goto error;
/* Replace bufPtr, bufLength with tmp versions (which must be freed) */
if( mustFreeBuf )
PGPFreeData( bufPtr );
mustFreeBuf = TRUE;
bufPtr = tmpBuf;
bufLength = tmpBufLength;
}
/* Process buffer to strip off any PKCS-7 layering */
{
PGPKeyDBObjRef dummy1, dummy2;
PGPBoolean dummy3, dummy4, dummy5;
PGPAttributeValue *dummy6;
PGPUInt32 dummy7;
err = X509InputCertificate( context, bufPtr, bufLength, refdb,
inputFormat, NULL, &dummy1, &dummy2,
&dummy3, &dummy4, &dummy5,
&dummy6, &dummy7, &certSet, &certSetLength,
&crlSet, &crlSetLength );
if( IsPGPError( err ) )
goto error;
if( IsntNull( certSet ) )
{
err = pgpDecodeX509CertSet( certSet, certSetLength, context,
refdb, db );
if( IsPGPError( err ) )
goto error;
}
if( IsntNull( crlSet ) )
{
err = pgpDecodeX509CRLSet( crlSet, crlSetLength, context, refdb,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -