📄 pgpkeylib.c
字号:
(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 */
/* Create empty keyset */
err = PGPNewKeySet( context, keys );
if( IsPGPError( err ) )
goto error;
/* Process the returned cert set */
if( IsntNull( certSet ) ) {
err = pgpDecodeX509CertSet( certSet, certSetLength,
context, &keys2 );
if( IsPGPError( err ) )
goto error;
err = PGPAddKeys( keys2, *keys );
if( IsPGPError( err ) )
goto error;
PGPFreeKeySet( keys2 );
keys2 = NULL;
}
/* Decode PKCS-8 data */
err = pgpDecodePCKS8( bufPtr, bufLength, context, &keys2 );
if( IsPGPError( err ) )
goto error;
/* Combine keysets */
err = PGPAddKeys( keys2, *keys );
if( IsPGPError( err ) )
goto error;
/* Set passphrase on newly imported key */
if( passphraseLength != 0 ) {
RingSet const *ringset;
RingIterator *ringiter;
ringset = pgpKeyDBRingSet ((*keys)->keyDB);
ringiter = ringIterCreate(ringset);
if (ringiter) {
/* Find key we just imported */
while (ringIterNextObject (ringiter, 1) == 1) {
key = ringIterCurrentObject (ringiter, 1);
if (ringKeyIsSec( ringset, key ) )
break;
key = NULL;
}
ringIterDestroy (ringiter);
}
if( key ) {
err = pgpDoChangePassphraseInternal( (*keys)->keyDB, ringset,
key, NULL, NULL, 0, passphrase, passphraseLength,
FALSE );
if( IsPGPError( err ) )
goto error;
/* Ringset for keydb may be changed by above call */
ringset = pgpKeyDBRingSet ((*keys)->keyDB);
}
}
err = PGPCommitKeyRingChanges( *keys );
if( IsPGPError( err ) )
goto error;
/* Done */
goto error;
}
if( inputFormat >= kPGPInputFormat_PEMEncodedX509Cert &&
inputFormat <= kPGPInputFormat_EntrustV1_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;
}
/* Now data is in bufPtr, of length bufLength */
err = pgpDecodeX509Cert( bufPtr, bufLength, context, keys );
error:
if( mustFreeBuf )
PGPFreeData( bufPtr );
if( IsntNull( certSet ) )
PGPFreeData( certSet );
if( IsntNull( keys2 ) )
PGPFreeKeySet( keys2 );
return err;
}
static const PGPOptionType impkeyOptionSet[] = {
kPGPOptionType_InputFileRef,
kPGPOptionType_LocalEncoding,
kPGPOptionType_InputBuffer,
kPGPOptionType_EventHandler,
kPGPOptionType_SendNullEvents,
kPGPOptionType_InputFormat,
kPGPOptionType_Passphrase,
kPGPOptionType_X509Encoding
};
/* Frees optionList, unlike most other internal functions */
PGPError
pgpImportKeySetInternal (PGPContextRef context, PGPKeySetRef *keys,
PGPOptionListRef optionList)
{
PGPError err = kPGPError_NoErr;
PGPKeySetRef keyset;
PGPInputFormat inputFormat;
PGPUInt32 fDo509;
if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
impkeyOptionSet, elemsof( impkeyOptionSet ) ) ) )
return err;
pgpAssertAddrValid( keys, PGPKeySetRef );
*keys = NULL;
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_X509Encoding, FALSE,
"%d", &fDo509 ) ) )
goto error;
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_InputFormat, FALSE,
"%d", &inputFormat ) ) )
goto error;
if( fDo509 || inputFormat >= kPGPInputFormat_X509DataInPKCS7 ) {
err = sImportX509Certificate( context, keys, inputFormat, optionList );
PGPFreeOptionList( optionList );
goto error;
}
if( IsPGPError( err = PGPNewKeySet( context, &keyset ) ) )
goto error;
if( IsPGPError( err = PGPDecode( context, optionList,
PGPODiscardOutput(context, TRUE),
PGPOImportKeysTo(context, keyset),
PGPOLastOption(context) ) ) ) {
PGPFreeKeySet( keyset );
goto error;
}
*keys = keyset;
error:
return err;
}
/*
* Handle X509 based export formats.
* Key is the top level key we are exporting; ringset controls which
* sub objects if any we should look at
*/
static PGPError
sExportKeyX509 (
PGPContextRef context,
PGPKeyRef key,
RingSet const *ringset,
PGPExportFormat exportFormat,
PGPOptionListRef optionList
)
{
PGPEnv *env;
PGPError err = kPGPError_NoErr;
PGPUInt32 fAppendOutput;
PGPPipeline *head = NULL, **tail = &head;
PFLConstFileSpecRef outFileRef;
PGPFile *pfout;
PGPByte *outBufPtr;
PGPByte **outBufPtrPtr;
PGPSize outBufMaxLength;
PGPSize *outBufUsedLength;
PGPPipeline *outPipe;
PGPByte *buf = NULL;
PGPSize bufLength = 0;
PGPBoolean freeBuf = FALSE;
PGPMemoryMgrRef mgr;
void *vFormatData;
PGPAttributeValue *formatData;
PGPAttributeValue *formatDataCopy = NULL;
PGPAttributeValue *newAV;
PGPSize formatDataLength;
PGPOptionListRef passphrase = NULL;
PGPByte *dpoint = NULL;
PGPSize dpointlen = 0;
static char s_pgpkeycr[] = "PGPKeyCreation=0x";
static PGPByte s_pgpx509keycr [] = {
0x30, 0x0e, /* SEQUENCE */
/* PGP Extension OID */
/* (1 3 6 1 4 1 3401 8 1 1) */
0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x9a, 0x49, 0x08,
0x01, 0x01,
0x04, 0x00 /* Octet string */
/* Value as UTCTime value goes here */
};
char pgpkeycr[40]; /* big enough for either case */
env = pgpContextGetEnvironment( context );
mgr = PGPGetContextMemoryMgr( context );
if (exportFormat == kPGPExportFormat_X509Cert) {
/* Find the right X509 sig, somehow */
RingObject *obj = NULL;
RingObject *bestsig = NULL;
RingIterator *ringiter;
PGPInt32 level;
ringiter = ringIterCreate (ringset);
if( IsNull( ringiter ) ) {
err = ringSetError( ringset )->error;
goto error;
}
while ((level = ringIterNextObjectAnywhere(ringiter)) > 0) {
obj = ringIterCurrentObject (ringiter, level);
if (ringObjectType(obj) == RINGTYPE_SIG &&
ringSigIsX509 (ringset, obj)) {
RingObject *signer = ringSigMaker (ringset, obj, ringset);
/* Use a self-sig if exists, else use first sig */
if (signer == ringIterCurrentObject (ringiter, 1)) {
bestsig = obj;
} else if (bestsig == NULL) {
bestsig = obj;
}
}
}
ringIterDestroy( ringiter );
if (bestsig != NULL) {
buf = ringSigX509Certificate( ringset, bestsig, &bufLength );
}
} else if (exportFormat >= kPGPExportFormat_X509GetCRL) {
time_t curtime = PGPGetStdTimeFromPGPTime( PGPGetTime() );
/* If InputBuffer is specified, it is CRL distribution point */
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_InputBuffer, FALSE,
"%p%l", &dpoint, &dpointlen ) ) )
goto error;
err = X509CreateCRLRequest ( context, key, dpoint, dpointlen,
exportFormat, curtime, &buf, &bufLength );
if( IsPGPError( err ) )
goto error;
freeBuf = TRUE;
} else if (exportFormat >= kPGPExportFormat_X509GetCertInitial) {
/* Structure for now will be a fixed empty sequence */
static PGPByte emptysequence[] = {0x30, 0x00};
buf = emptysequence;
bufLength = sizeof(emptysequence);
freeBuf = FALSE;
} else if (exportFormat >= kPGPExportFormat_X509CertReq) {
PGPOption passop;
if( IsPGPError( err = pgpSearchOptionSingle( optionList,
kPGPOptionType_Passphrase, &passop ) ) )
goto error;
if( IsntOp( passop ) ) {
if( IsPGPError( err = pgpSearchOptionSingle( optionList,
kPGPOptionType_Passkey, &passop ) ) )
goto error;
}
if( IsOp( passop ) ) {
PGPOption passopcopy;
pgpCopyOption( context, &passop, &passopcopy );
passphrase = pgpNewOneOptionList( context, &passopcopy );
}
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_AttributeValue, FALSE,
"%p%l",
&vFormatData, &formatDataLength ) ) )
goto error;
formatData = vFormatData;
formatDataLength /= sizeof(PGPAttributeValue);
formatDataCopy = PGPNewData( mgr,
(formatDataLength+1)*sizeof(PGPAttributeValue), 0 );
if( IsNull( formatDataCopy ) ) {
err = kPGPError_OutOfMemory;
goto error;
}
pgpCopyMemory( formatData, formatDataCopy+1,
formatDataLength*sizeof(PGPAttributeValue) );
newAV = formatDataCopy;
/* Add "description" or extension field to hold keycreation data */
if( exportFormat == kPGPExportFormat_VerisignV1_CertReq )
{
/* Use a new extension */
PGPUInt32 kcr = ringKeyCreation (ringset, key->key);
PGPByte *px = (PGPByte *)pgpkeycr + sizeof(s_pgpx509keycr);
PGPSize tlen;
char tbuf[PGPX509TIMELEN+1];
tlen = pgpTimeToX509Time( kcr, tbuf );
pgpCopyMemory( s_pgpx509keycr, pgpkeycr, sizeof(s_pgpx509keycr) );
pgpkeycr[1] += tlen + 2;
pgpkeycr[sizeof(s_pgpx509keycr)-1] += tlen + 2;
/* Choose GeneralizedTime vs UTCTime tag */
*px++ = (tlen == PGPX509TIMELEN) ? 24 : 23;
*px++ = tlen;
pgpCopyMemory( tbuf, px, tlen );
newAV->attribute = kPGPAVAttribute_CertificateExtension;
newAV->size = sizeof(s_pgpx509keycr) + 2 + tlen;
newAV->value.pointervalue = pgpkeycr;
newAV->unused = 0;
}
else
{
/* Use description field in subject name */
pgpCopyMemory( s_pgpkeycr, pgpkeycr, sizeof(s_pgpkeycr)-1 );
sprintf ( pgpkeycr+sizeof(s_pgpkeycr)-1, "%08x",
ringKeyCreation (ringset, key->key) );
newAV->attribute = kPGPAVAttribute_Description;
newAV->size = sizeof(s_pgpkeycr)-1 + 8;
newAV->value.pointervalue = pgpkeycr;
newAV->unused = 0;
}
err = X509CreateCertificateRequest ( context, key, exportFormat,
formatDataCopy, formatDataLength+1, passphrase,
&buf, &bufLength );
passphrase = NULL;
PGPFreeData( formatDataCopy );
formatDataCopy = NULL;
if( IsPGPError( err ) )
goto error;
freeBuf = TRUE;
} else {
pgpAssert (0);
}
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_AppendOutput, FALSE,
"%d", &fAppendOutput ) ) )
goto error;
err = pgpSetupOutputPipeline( context, optionList,
env, FALSE, FALSE, FALSE,
(PGPBoolean)fAppendOutput, TRUE,
&tail, &outFileRef, &pfout,
&outBufPtr, &outBufPtrPtr,
&outBufMaxLength, &outBufUsedLength,
&outPipe );
if( IsPGPError( err ) )
goto error;
err = pgpPumpMem( head, buf, bufLength, NULL, NULL );
if( IsPGPError( err ) )
goto error;
if( outPipe ) {
if( IsntNull( outBufPtrPtr ) ) {
/* Dynamically allocated buffer - tell user size & position */
if( IsPGPError( err = pgpGetVariableMemOutput( outPipe,
outBufMaxLength, outBufPtrPtr,
outBufUsedLength ) ) )
goto error;
} else {
/* Fixed size buffer - tell user actual size used */
pgpAssert( IsntNull( outBufPtr ) );
if( IsPGPError( err = pgpGetMemOutput( outPipe,
outBufMaxLength, outBufUsedLength ) ) )
goto error;
}
}
head->teardown( head );
head = NULL;
error:
if( IsntNull( passphrase ) )
pgpFreeOptionList( passphrase );
if( IsntNull( formatDataCopy ) )
PGPFreeData( formatDataCopy );
if( freeBuf && IsntNull( buf ) )
PGPFreeData( buf );
if( IsntNull( head ) )
head->teardown( head );
return err;
}
/*
* Filter function for extraction. Remove any secret objects.
* If addarrs is true, also add any additional decryption key objects to
* the set. This will cause ADK's to be extracted with the keys
* that use them.
* XXX AUTOMATIC ADK EXTRACTION DOES NOT YET WORK.
* There is no RingSet available in which
* to look for ADK's. The export functions typically are called with
* just a memory RingSet. We need to add versions which take an extra
* PGPKeySet to flag that ADK's should be looked for there.
*/
static RingSet *
filterPubRingSet (RingSet const *rset,
PGPBoolean exportmastersecrets, PGPBoolean exportsubsecrets,
PGPBoolean addarks, PGPBoolean includeattributes)
{
RingSet *rsetnew; /* Set of recipients */
RingSet *adkeyset; /* Set of additional decryption keys */
RingIterator *riter; /* Iterator over adding sets */
int level;
PGPBoolean exportsecrets = exportmastersecrets;
PGPError err = kPGPError_NoErr;
if (!rset)
return NULL;
adkeyset = NULL;
rsetnew = ringSetCreate (ringSetPool (rset));
if (!rsetnew)
return NULL;
riter = ringIterCreate (rset);
if (!riter) {
ringSetDestroy (rsetnew);
return NULL;
}
/*
* Copy objects in PGPKeySet to rsetnew except secret objects.
* At the same time, accumulate any additional decryption keys into
* adkeyset.
*/
while ((level = ringIterNextObjectAnywhere(riter)) > 0) {
RingObject *obj = ringIterCurrentObject (riter, level);
if (ringObjectType(obj) == RINGTYPE_KEY) {
exportsecrets = ringKeyIsSubkey(rset, obj) ? exportsubsecrets :
exportmastersecrets;
}
/* Possibly skip secret objects */
if (!exportsecrets && ringObjectType (obj) == RINGTYPE_SEC)
continue;
/* Skip signatures if exporting secret keys */
if (exportsecrets && ringObjectType (obj) == RINGTYPE_SIG)
continue;
if (!includeattributes && ringObjectType (obj) == RINGTYPE_NAME
&& ringNameIsAttribute (rset, obj))
continue;
if (!includeattributes && ringObjectType (obj) == RINGTYPE_SIG) {
RingObject *parent = ringIterCurrentObject (riter, level-1);
if (ringObjectType(parent) == RINGTYPE_NAME &&
ringNameIsAttribute (rset, parent))
continue;
}
ringSetAddObject (rsetnew, obj);
/* For key objects, look for additional decryption keys */
if (addarks && ringObjectType (obj) == RINGTYPE_KEY)
{
RingObject *rkey; /* Decryption key */
unsigned nrkeys; /* Number of decryption keys */
if (ringKeyAdditionalRecipientRequestKey (obj, rset, 0, NULL,
NULL, NULL, &nrkeys, &err) != NULL )
{
/* Add to special set for additional decryption keys */
while (nrkeys-- > 0)
{
rkey = ringKeyAdditionalRecipientRequestKey (obj, rset, 0,
NULL, NULL, NULL, &nrkeys, &err);
pgpAssert (rkey);
if (!adkeyset)
{
adkeyset = ringSetCreate (ringSetPool(rset));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -