📄 pgpkeyio.c
字号:
IsntNull(*db)?&db2:db );
if( IsPGPError( err ) )
goto error;
if( IsNull( *db ) )
{
err = kPGPError_X509NeededCertNotAvailable;
goto error;
}
/* Combine keysets if necessary */
if( IsntNull( db2 ) )
{
PGPKeySetRef crls;
err = PGPCopyKeys( pgpKeyDBPeekRootSet(db2), *db, &crls );
if( IsPGPError( err ) )
goto error;
PGPFreeKeyDB( db2 );
db2 = NULL;
/* Run a sig check to make CRL effective */
PGPCheckKeyRingSigs( crls, NULL, FALSE, NULL, NULL );
}
else
{
/* Run a sig check to make CRL effective */
PGPCheckKeyRingSigs( pgpKeyDBPeekRootSet(*db), NULL,
FALSE, NULL, NULL );
}
}
}
error:
if( mustFreeBuf )
PGPFreeData( bufPtr );
if( IsntNull( certSet ) )
PGPFreeData( certSet );
if( IsntNull( crlSet ) )
PGPFreeData( crlSet );
if( IsntNull( db2 ) )
PGPFreeKeyDB( db2 );
return err;
}
static const PGPOptionType impkeyOptionSet[] = {
kPGPOptionType_InputFileRef,
kPGPOptionType_LocalEncoding,
kPGPOptionType_InputBuffer,
kPGPOptionType_EventHandler,
kPGPOptionType_SendNullEvents,
kPGPOptionType_InputFormat,
kPGPOptionType_Passphrase,
kPGPOptionType_CachePassphrase,
kPGPOptionType_X509Encoding,
kPGPOptionType_KeyDBRef
};
/* Frees optionList, unlike most other internal functions */
PGPError
pgpImportKeySetInternal (PGPContextRef context, PGPKeyDBRef *keydb,
PGPOptionListRef optionList)
{
PGPError err = kPGPError_NoErr;
PGPKeyDBRef kdb;
PGPInputFormat inputFormat;
PGPUInt32 fDo509;
if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
impkeyOptionSet, elemsof( impkeyOptionSet ) ) ) )
return err;
pgpAssertAddrValid( keydb, PGPKeyDBRef );
*keydb = 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, keydb, inputFormat, optionList);
PGPFreeOptionList( optionList );
goto error;
}
if( IsPGPError( err = PGPNewKeyDB( context, &kdb ) ) )
goto error;
if( IsPGPError( err = PGPDecode( context, optionList,
PGPODiscardOutput(context, TRUE),
PGPOImportKeysTo(context, kdb),
PGPOLastOption(context) ) ) ) {
PGPFreeKeyDB( kdb );
goto error;
}
*keydb = kdb;
error:
return err;
}
/*
* Add our custom PGP X.509 extension, if useExtension is true. Else add
* the data to the description field. Fill into *av. buf is a working
* buff at least 40 bytes long. key tells which key to get the PGP data
* from.
*/
static void
sAddPGPX509Extension( PGPAttributeValue *av, char *buf, PGPKeyDBObjRef key,
PGPBoolean useExtension )
{
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 */
};
if( useExtension )
{
/* Use a new extension */
PGPUInt32 kcr = pgpKeyCreation (key);
PGPByte *px = (PGPByte *)buf + sizeof(s_pgpx509keycr);
PGPSize tlen;
char tbuf[PGPX509TIMELEN+1];
tlen = pgpTimeToX509Time( kcr, tbuf );
pgpCopyMemory( s_pgpx509keycr, buf, sizeof(s_pgpx509keycr) );
buf[1] += tlen + 2;
buf[sizeof(s_pgpx509keycr)-1] += tlen + 2;
/* Choose GeneralizedTime vs UTCTime tag */
*px++ = (tlen == PGPX509TIMELEN) ? 24 : 23;
*px++ = tlen;
pgpCopyMemory( tbuf, px, tlen );
av->attribute = kPGPAVAttribute_CertificateExtension;
av->size = sizeof(s_pgpx509keycr) + 2 + tlen;
av->value.pointervalue = buf;
av->unused = 0;
}
else
{
/* Use description field in subject name */
pgpCopyMemory( s_pgpkeycr, buf, sizeof(s_pgpkeycr)-1 );
sprintf ( buf+sizeof(s_pgpkeycr)-1, "%08x",
pgpKeyCreation (key) );
av->attribute = kPGPAVAttribute_Description;
av->size = sizeof(s_pgpkeycr)-1 + 8;
av->value.pointervalue = buf;
av->unused = 0;
}
}
/*
* Handle X509 based export formats.
* Key is the top level key we are exporting; keyset controls which
* sub objects if any we should look at
*/
static PGPError
sExportKeyX509 (
PGPKeyDBObjRef key,
PGPKeySetRef keyset,
PGPExportFormat exportFormat,
PGPOptionListRef optionList
)
{
PGPContextRef context;
PGPKeyDBRef kdb;
PGPError err = kPGPError_NoErr;
PGPByte *buf = NULL;
PGPSize bufLength = 0;
PGPBoolean freeBuf = FALSE;
PGPUInt32 fExportSecrets;
PGPMemoryMgrRef mgr;
void *vFormatData;
PGPAttributeValue *formatData;
PGPAttributeValue *formatDataCopy = NULL;
PGPAttributeValue *newAV;
PGPSize formatDataLength;
PGPOptionListRef passphrase = NULL;
PGPByte *dpoint = NULL;
PGPSize dpointlen = 0;
PGPInt32 annotate = 0;
char pgpkeycr[40]; /* big enough for either case */
kdb = PGPPeekKeyDBObjKeyDB( key );
context = PGPPeekKeyDBContext( kdb );
mgr = PGPPeekContextMemoryMgr( context );
if (exportFormat == kPGPExportFormat_X509Cert) {
/* Find the right X509 sig, somehow */
PGPKeyDBObj *obj = NULL;
PGPKeyDBObj *bestsig = NULL;
PGPKeyIter *iter;
if( IsPGPError( err = PGPNewKeyIterFromKeySet( keyset, &iter ) ) )
goto error;
while( IsntPGPError( pgpKeyIterNextObject( iter, &obj ) ) ) {
if (pgpObjectType(obj) == RINGTYPE_SIG &&
pgpSigIsX509 (obj)) {
PGPKeyDBObj *signer = pgpSigMaker (obj);
/* Use a self-sig if exists, else use first sig */
if (signer == obj->up) {
bestsig = obj;
} else if (bestsig == NULL) {
bestsig = obj;
}
}
}
PGPFreeKeyIter( iter );
iter = NULL;
if (bestsig != NULL) {
buf = pgpSigX509Certificate( bestsig, &bufLength );
}
annotate = PGPANN_ARMORX509_CERTIFICATE;
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_ExportPrivateKeys, FALSE,
"%d", &fExportSecrets ) ) )
goto error;
if( fExportSecrets )
{
/* Do PKCS-12 conversion */
PGPByte *password;
PGPSize passwordLength;
PGPByte *p8buf;
PGPSize p8buflen;
PGPByte *p12buf;
PGPSize p12buflen;
PGPByte *friendlyName;
PGPSize friendlyLen;
PGPSecKey *seckey;
PGPKeyDBObjRef userID;
if( IsPGPError( err = pgpFindOptionArgs( optionList,
kPGPOptionType_Passphrase, FALSE,
"%p%l", &password, &passwordLength ) ) )
goto error;
seckey = pgpSecSecKey (key, PGP_PKUSE_SIGN);
if (!seckey)
{
err = pgpKeyDBError(PGPPeekKeyDBObjKeyDB(key));
goto error;
}
err = pgpSecKeyUnlock( seckey, (char *) password, passwordLength, FALSE );
if( err != 1 )
{
err = kPGPError_BadPassphrase;
goto error;
}
err = pgpEncodePKCS8( seckey, &p8buf, &p8buflen );
pgpSecKeyDestroy( seckey );
if( IsPGPError( err ) )
goto error;
PGPGetPrimaryUserID( key, &userID );
pgpGetUserIDAllocatedStringBuffer( userID, kPGPUserIDProperty_Name,
&friendlyName, &friendlyLen );
err = pgpCreateCertSetFromChain( context, bestsig, &buf,
&bufLength );
if( IsPGPError( err ) )
{
PGPFreeData( friendlyName );
PGPFreeData( p8buf );
goto error;
}
err = PKCS12ExportKey( context, p8buf, p8buflen, password,
passwordLength, buf, bufLength,
friendlyName, friendlyLen,
1, 1000, kPGPPBEAlgorithm_SHA3DES,
&p12buf, &p12buflen );
PGPFreeData( buf );
PGPFreeData( p8buf );
PGPFreeData( friendlyName );
if( IsPGPError( err ) )
goto error;
buf = p12buf;
bufLength = p12buflen;
freeBuf = TRUE;
annotate = PGPANN_ARMORX509_PRIVATE;
}
} 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 */
sAddPGPX509Extension( newAV, pgpkeycr, key,
(PGPBoolean)(exportFormat==kPGPExportFormat_VerisignV1_CertReq ) );
err = X509CreateCertificateRequest ( context, key, exportFormat,
formatDataCopy, formatDataLength+1, passphrase,
&buf, &bufLength );
passphrase = NULL;
PGPFreeData( formatDataCopy );
formatDataCopy = NULL;
if( IsPGPError( err ) )
goto error;
freeBuf = TRUE;
annotate = PGPANN_ARMORX509_CERT_REQUEST;
} else {
pgpAssert (0);
}
err = pgpOutputBufferByOptionList( context, buf, bufLength, optionList, annotate );
error:
if( IsntNull( passphrase ) )
pgpFreeOptionList( passphrase );
if( IsntNull( formatDataCopy ) )
PGPFreeData( formatDataCopy );
if( freeBuf && IsntNull( buf ) )
PGPFreeData( buf );
return err;
}
static const PGPOptionType cx509OptionSet[] = {
kPGPOptionType_Passphrase,
kPGPOptionType_Passkey,
kPGPOptionType_CachePassphrase,
kPGPOptionType_InputFileRef,
kPGPOptionType_LocalEncoding,
kPGPOptionType_InputBuffer,
kPGPOptionType_AttributeValue,
kPGPOptionType_Expiration,
kPGPOptionType_CreationDate
};
/*
* Create X.509 certificate. If targetkey is NULL use PKCS-10 request
* from PGPOInput options instead.
*/
PGPError
pgpCreateX509CertificateInternal(
PGPKeyDBObjRef signer,
PGPKeyDBObjRef targetkey,
PGPKeyDBObjRef *sig,
PGPOptionListRef optionList
)
{
PGPContextRef context;
PGPMemoryMgrRef mgr;
char * passphrase;
PGPSize passphraseLength;
PGPBoolean hashedPhrase = FALSE;
PGPTime creationTime;
PGPUInt32 expirationDays;
PGPError err;
void *vFormatData;
PGPAttributeValue *formatData;
PGPAttributeValue *formatDataCopy = NULL;
PGPSize formatDataLength;
PGPByte *pkcs10Buffer = NULL;
PGPSize pkcs10BufferSize;
PGPBoolean mustFreeBuf = FALSE;
char pgpkeycr[40]; /* big enough for custom ext. */
if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
cx509OptionSet, elemsof( cx509OptionSet ) ) ) )
return err;
context = PGPPeekKeyDBObjContext( signer );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -