📄 pgpx509keys.c
字号:
bnlen[1] = elgp->g.len;
err = sDecodeX509Integer (bnbuf[1], bnlen[1], NULL, &bnlength[1]);
if( IsPGPError( err ) )
goto error;
/* public value y */
bnbuf[2] = elgk->val;
bnlen[2] = elgk->len;
err = sDecodeX509Integer (bnbuf[2], bnlen[2], NULL, &bnlength[2]);
if( IsPGPError( err ) )
goto error;
pubelems = 3;
} else /* RSA */ {
pgpasn_UnpackRSAKey ( asnctx, &rsak, spki->subjectPublicKey.val,
spki->subjectPublicKey.len, &err );
CHKASNERR( err );
/* modulus n */
bnbuf[0] = rsak->modulus.val;
bnlen[0] = rsak->modulus.len;
err = sDecodeX509Integer (bnbuf[0], bnlen[0], NULL, &bnlength[0]);
if( IsPGPError( err ) )
goto error;
/* exponent e */
bnbuf[1] = rsak->exponent.val;
bnlen[1] = rsak->exponent.len;
err = sDecodeX509Integer (bnbuf[1], bnlen[1], NULL, &bnlength[1]);
if( IsPGPError( err ) )
goto error;
pubelems = 2;
}
}
keybuflength = 0;
publength = 0;
for (i=0; i<elemsof(bnlength); ++i) {
if( bnlength[i] == 0 )
break;
if (i < pubelems)
publength += bnlength[i];
keybuflength += bnlength[i];
}
/*
* To better estimate keybuflength, we need to construct the numeric
* data portion and then see if it matches an incoming key. Only then
* can we know what kind of key packet we are dealing with.
*/
pubbuf = PGPNewData (mgr, publength, 0);
CHKNONNULL(pubbuf, err);
o = 0;
for (i=0; i<pubelems; ++i) {
if( bnlength[i] == 0 )
break;
err = sDecodeX509Integer (bnbuf[i], bnlen[i],
pubbuf+o, &bnlength[i]);
if( IsPGPError( err ) )
goto error;
o += bnlength[i];
}
pgpAssert (o == publength);
/* Get hash of numeric data */
pgpFingerprint20HashBuf (context, pubbuf, publength, hash20);
/* See if this matches an existing key */
matchkey = ringPoolFindKey20n (pool, hash20);
if( IsNull( matchkey ) ) {
/* Fall back on defaults */
if (keyalgorithm == kPGPPublicKeyAlgorithm_RSA)
keyversion = PGPVERSION_3;
else
keyversion = PGPVERSION_4;
} else {
RingSet *allset;
allset = ringSetCreateUniversal (pool);
if( IsNull( allset ) ) {
err = ringPoolError(pool)->error;
goto error;
}
matchkeybuf = ringFetchObject (allset, matchkey, &matchkeybuflength);
ringSetDestroy( allset );
if( IsNull( matchkeybuf ) ) {
ringSetDestroy( allset );
err = ringPoolError(pool)->error;
goto error;
}
keyversion = matchkeybuf[0];
}
keybuflength += 6; /* bytes preceding bignums */
if( keyversion <= PGPVERSION_3)
keybuflength += 2; /* room for expiration date */
if( IsntNull( pinfo ) ) {
/*
* Can only import private if we have a matching key,
* because we can't synthesize a userid for it
*/
if( IsNull( matchkey ) ) {
err = kPGPError_PublicKeyNotFound;
goto error;
}
keybuflength += 3; /* Private adds 1 enc byte + 2 csum */
}
if( IsNull( keyBuf ) ) {
*keyLength = keybuflength;
} else {
pgpAssert (*keyLength == keybuflength);
/* public key packet */
o = 0;
keyBuf[o++] = keyversion;
/* 1-4 are timestamp */
if (IsntNull( matchkey ) ) {
pgpCopyMemory (matchkeybuf+1, keyBuf+o, 4);
} else {
PGPUInt32 creation = sDecodeKeyCreation( asnctx, cert );
if( creation != 0 ) {
keyBuf[o+0] = (creation >> 24) & 0xff;
keyBuf[o+1] = (creation >> 16) & 0xff;
keyBuf[o+2] = (creation >> 8) & 0xff;
keyBuf[o+3] = (creation >> 0) & 0xff;
} else {
/* Use certificate creation date if all else fails */
err = sDecodeNotBefore4( asnctx, cert, keyBuf+o );
if (IsPGPError( err ) ) {
pgpClearMemory (keyBuf+o, 4);
err = kPGPError_NoErr;
}
}
}
o += 4;
/* Next two are expiration if V3 packets */
if (keyversion <= PGPVERSION_3) {
if (IsntNull( matchkey ) ) {
pgpCopyMemory (matchkeybuf+5, keyBuf+o, 2);
} else {
pgpClearMemory (keyBuf+o, 2);
}
o += 2;
}
keyBuf[o++] = keyalgorithm;
pgpCopyMemory (pubbuf, keyBuf+o, publength);
o += publength;
PGPFreeData( pubbuf );
pubbuf = NULL;
if( IsntNull( pinfo ) ) {
/* Save secret key fields */
keyBuf[o++] = '\0'; /* Unencrypted secret data */
checksum = 0;
for (i=pubelems; i<elemsof(bnlength); ++i) {
if( bnlength[i] == 0 )
break;
err = sDecodeX509Integer (bnbuf[i], bnlen[i],
keyBuf+o, &bnlength[i]);
if( IsPGPError( err ) )
goto error;
for (j=0; j<bnlength[i]; ++j)
checksum += keyBuf[o+j];
o += bnlength[i];
}
keyBuf[o++] = (checksum >> 8) & 0xff;
keyBuf[o++] = (checksum >> 0) & 0xff;
}
pgpAssert (o == keybuflength);
}
error:
if( IsntNull( pubbuf ) )
PGPFreeData( pubbuf );
if( IsntNull( dssp ) )
pgpasn_FreeDssParms( asnctx, dssp );
if( IsntNull( dssk ) )
pgpasn_FreeDSAPublicKey( asnctx, dssk );
if( IsntNull( elgp ) )
pgpasn_FreeELGParms( asnctx, elgp );
if( IsntNull( elgk ) )
pgpasn_FreeELGPublicKey( asnctx, elgk );
if( IsntNull( rsak ) )
pgpasn_FreeRSAKey( asnctx, rsak );
if( IsntNull( rsapriv ) )
pgpasn_FreeRSAPrivateKey( asnctx, rsapriv );
return err;
}
/*
* Given an X509 cert, return a PGPKeySetRef containing a simple PGP key
* with the same key material as the original cert. The userid on the
* key is one of the 509 subject distinguished name fields, the common name
* if it exists, else one of the other fields.
*/
static PGPError
sDecode509(PGPContextRef context, PGPASN_CONTEXT *asnctx,
PGPASN_Certificate *cert, PGPKeySetRef *kset)
{
PGPMemoryMgrRef mgr;
PGPByte *pgpkeybuf = NULL;
PGPSize keylen;
PGPSize namelen;
PGPSize siglen;
PGPSize pgpkeylen;
PGPUInt32 o;
PGPKeySetRef keyset;
PGPError err = kPGPError_NoErr;
*kset = NULL;
mgr = PGPGetContextMemoryMgr( context );
/* Decode signature packet */
err = sDecodeSig (context, asnctx, cert, SIGSUBSUB_X509_VERSION_LO,
NULL, &siglen);
if (IsPGPError(err))
goto error;
/* Decode subject name */
err = sDecodeName (asnctx, cert, FALSE, NULL, &namelen);
if (IsPGPError(err))
goto error;
/* Decode key packet */
err = sDecodeKey (context, asnctx, cert, NULL, NULL, &keylen);
if (IsPGPError(err))
goto error;
/* Now create the PGP key */
pgpkeylen = 3 + keylen + 3 + namelen + ((siglen>0)?(3+siglen):0);
pgpkeybuf = (PGPByte *) PGPNewData( mgr, pgpkeylen, 0 );
CHKNONNULL (pgpkeybuf, err);
/* public key packet */
o = 0;
pgpkeybuf[o++] = PKTBYTE_BUILD(PKTBYTE_PUBKEY, 1),
pgpkeybuf[o++] = (keylen >> 8) & 0xff;
pgpkeybuf[o++] = (keylen >> 0) & 0xff;
err = sDecodeKey (context, asnctx, cert, NULL, pgpkeybuf + o, &keylen);
if (IsPGPError(err))
goto error;
o += keylen;
/* userid packet */
pgpkeybuf[o++] = PKTBYTE_BUILD(PKTBYTE_NAME, 1);
pgpkeybuf[o++] = (namelen >> 8) & 0xff;
pgpkeybuf[o++] = (namelen >> 0) & 0xff;
err = sDecodeName (asnctx, cert, FALSE, pgpkeybuf + o, &namelen);
if (IsPGPError(err))
goto error;
o += namelen;
/* sig packet */
pgpkeybuf[o++] = PKTBYTE_BUILD(PKTBYTE_SIG, 1);
pgpkeybuf[o++] = (siglen >> 8) & 0xff;
pgpkeybuf[o++] = (siglen >> 0) & 0xff;
err = sDecodeSig (context, asnctx, cert, SIGSUBSUB_X509_VERSION_LO,
pgpkeybuf + o, &siglen);
if (IsPGPError(err))
goto error;
o += siglen;
pgpAssert (o == pgpkeylen);
err = pgpImportKeyBinary( context, pgpkeybuf, pgpkeylen, &keyset );
if( IsPGPError( err ) )
goto error;
*kset = keyset;
/* Fall through */
error:
if( IsntNull(pgpkeybuf) )
PGPFreeData( pgpkeybuf );
return err;
}
/* Entry point to import a 509 cert from the specified location */
PGPError
pgpDecodeX509Cert( PGPByte *buf, PGPSize len, PGPContextRef context,
PGPKeySetRef *keys )
{
PGPASN_Certificate *cert;
PGPMemoryMgrRef mgr;
PGPASN_CONTEXT asnctx_static, *asnctx = &asnctx_static;
PGPASN_MemoryMgr asnmem;
PGPError err = kPGPError_NoErr;
mgr = PGPGetContextMemoryMgr( context );
sSetupASNCONTEXT (mgr, asnctx, &asnmem);
pgpasn_UnpackCertificate( asnctx, &cert, buf, len, &err );
CHKASNERR( err )
err = sDecode509( context, asnctx, cert, keys);
pgpasn_FreeCertificate( asnctx, cert );
error:
return err;
}
/* Entry point to import a SET OF X509 certs */
PGPError
pgpDecodeX509CertSet(PGPByte *buf, PGPSize len, PGPContextRef context,
PGPKeySetRef *kset)
{
PGPASN_Certificates *certs = NULL;
PGPASN_Certificate *cert;
PGPMemoryMgrRef mgr;
PGPASN_CONTEXT asnctx_static, *asnctx = &asnctx_static;
PGPASN_MemoryMgr asnmem;
PGPKeySetRef newkset = NULL;
PGPKeySetRef tmpkset = NULL;
PGPInt32 i;
PGPError err = kPGPError_NoErr;
mgr = PGPGetContextMemoryMgr( context );
sSetupASNCONTEXT (mgr, asnctx, &asnmem);
pgpAssert( IsntNull( kset ) );
*kset = NULL;
if( IsPGPError( err = PGPNewKeySet( context, &newkset ) ) )
goto error;
pgpasn_UnpackCertificates( asnctx, &certs, buf, len, &err );
CHKASNERR( err );
for (i=0; i<certs->n; ++i) {
cert = certs->elt[i];
err = sDecode509( context, asnctx, cert, &tmpkset );
CHKASNERR( err );
PGPAddKeys( tmpkset, newkset );
PGPCommitKeyRingChanges( newkset );
PGPFreeKeySet( tmpkset );
tmpkset = NULL;
}
error:
if( IsntNull( certs ) )
pgpasn_FreeCertificates( asnctx, certs );
if( IsntNull( tmpkset ) )
PGPFreeKeySet( tmpkset );
if( IsntPGPError( err ) )
*kset = newkset;
else if( IsntNull( newkset ) )
PGPFreeKeySet( newkset );
return err;
}
/* Entry point to import a SET OF X509 CRLs */
PGPError
pgpDecodeX509CRLSet(PGPByte *buf, PGPSize len,
PGPContextRef context, PGPKeySet *kset)
{
PGPASN_CertificateRevocationLists *crls = NULL;
PGPASN_CertificateRevocationList *crl;
PGPASN_Extension *ext;
PGPASN_DistributionPointName *dpname;
PGPASN_GeneralNames *gnames;
PGPASN_IssuingDistributionPoint *dpt = NULL;
PGPMemoryMgrRef mgr;
PGPASN_CONTEXT asnctx_static, *asnctx = &asnctx_static;
PGPASN_MemoryMgr asnmem;
RingPool *pool = pgpContextGetRingPool( context );
RingSet *newset = NULL;
RingObject *crlkey;
RingObject *crlobj;
PGPPubKey *pubkey = NULL;
PGPByte *pgpcrlbuf = NULL;
PGPSize pgpcrllen;
PGPByte *crlbuf = NULL;
PGPSize crllen;
PGPByte *namebuf = NULL;
PGPSize namebuflen;
PGPByte *dpoint = NULL; /* Dynamically allocated */
PGPSize dpointlen;
PGPInt32 i, j;
PGPError err = kPGPError_NoErr;
mgr = PGPGetContextMemoryMgr( context );
sSetupASNCONTEXT (mgr, asnctx, &asnmem);
pgpasn_UnpackCertificateRevocationLists( asnctx, &crls, buf, len, &err );
CHKASNERR( err );
newset = ringSetCreate( pool );
if( IsNull( newset ) ) {
err = ringPoolError(pool)->error;
goto error;
}
for (i=0; i<crls->n; ++i) {
crl = crls->elt[i];
/* Look up CRL to see if we have issuing key */
namebuflen = pgpasn_SizeofName( asnctx,
&crl->tbsCertList.issuer, TRUE );
namebuf = (PGPByte *) PGPNewData( mgr, namebuflen, 0 );
CHKNONNULL( namebuf, err );
pgpasn_PackName (asnctx, namebuf, namebuflen, &crl->tbsCertList.issuer,
&err );
CHKASNERR( err );
crlkey = ringPoolFindX509NamedSig (pool, namebuf, namebuflen);
PGPFreeData( namebuf );
namebuf = NULL;
if( IsNull( crlkey ) ) {
/* Don't have a key the CRL is for, skip it! */
continue;
}
ringSetAddObject( newset, crlkey );
/* Actualy the above call returns a sig on the key we want */
pgpAssert( OBJISSIG( crlkey ) );
while (!OBJISTOPKEY( crlkey ) )
crlkey = crlkey->g.up;
/* See if CRL is properly signed */
pubkey = ringKeyPubKey(newset, crlkey, PGP_PKUSE_SIGN);
if (!pubkey) {
/* Can't verify this sig for some reason, try next */
continue;
}
crllen = pgpasn_SizeofCertificateRevocationList( asnctx, crl, TRUE );
crlbuf = (PGPByte *) PGPNewData( mgr, crllen, TRUE );
CHKNONNULL( crlbuf, err );
pgpasn_PackCertificateRevocationList( asnctx, crlbuf, crllen, crl,
&err );
CHKASNERR( err );
err = pgpX509VerifySignedObject( context, pubkey, crlbuf, crllen );
PGPFreeData( crlbuf );
crlbuf = NULL;
pgpPubKeyDestroy( pubkey );
pubkey = NULL;
if( IsPGPError( err ) ) {
/* Couldn't verify sig, skip CRL */
err = kPGPError_NoErr;
continue;
}
/* See if CRL has distribution point */
dpoint = NULL;
dpointlen = 0;
if( IsntNull( crl->tbsCertList.crlExtensions ) ) {
for (j=0; j<crl->tbsCertList.crlExtensions->n; ++j) {
ext = crl->tbsCertList.crlExtensions->elt[j];
if (ext->extnID.len == sizeof(issdistpoint)
&& memcmp(ext->extnID.val, issdistpoint,
ext->extnID.len)==0 ) {
/* Parse distribution point */
pgpasn_UnpackIssuingDistributionPoint ( asnctx, &dpt,
ext->extnValue.val, ext->extnValue.len, &err );
if( err == 0 &&
IsntNull( dpt->distributionPoint ) ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -