📄 pgpreconstruct.c
字号:
if( !strlen( serverURL ) )
{
err = kPGPError_BadParams;
goto done;
}
if( serverClass == kPGPKeyServerClass_PGP )
{
/*
* We have the hashed passphrases in inPassInfo[...] and the
* number of hash repetitions in con->hashReps.
*/
err = PGPNewLDAPContext( con->context, &ldap ); CKERR;
if( IsNull( ldap ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
strcat( serverURL, "/" );
err = PGPldapURLParse( ldap, serverURL, &lud ); CKERR;
if( strstr( serverURL, "ldaps://" ) != NULL )
bSecure = TRUE;
if( lud->port == 0 )
lud->port = bSecure ? kPGPldap_DefaultSecurePort : kPGPldap_DefaultPort;
err = PGPldapOpen( ldap, lud->host, lud->port ); CKERR;
if( bSecure )
{
err = sEstablishTLSSession( con->context,
ldap,
&tlsContext,
&tlsSession );
if( IsPGPError( err ) )
{
(void) sSendTLSEvent( con->context, con->handler, con->userValue,
kPGPKeyServerState_TLSUnableToSecureConnection, tlsSession );
goto done;
}
else
{
err = sSendTLSEvent( con->context, con->handler, con->userValue,
kPGPKeyServerState_TLSConnectionSecured, tlsSession ); CKERR;
}
}
err = PGPNewHashContext( con->context,
kPGPHashAlgorithm_SHA, &hashCon ); CKERR;
/* Hash all 5 outer keys */
PGPUInt32ToEndian( kReconOuterMagic, kPGPBigEndian, hashMagic );
for( shareIndex = 0; shareIndex < kPGPRecon_NumShares; shareIndex++ )
{
for( hashIndex = 0; hashIndex < con->hashReps; hashIndex++ )
{
(void) PGPContinueHash( hashCon, inPassInfo[shareIndex],
strlen( inPassInfo[shareIndex] ) );
(void) PGPContinueHash( hashCon, hashMagic, sizeof(hashMagic) );
}
err = PGPFinalizeHash( hashCon, hashOut ); CKERR;
err = PGPResetHash( hashCon ); CKERR;
pgpCopyMemory( hashOut, passKey[shareIndex], kReconstructWrapKeySize );
pgpClearMemory( hashOut, sizeof(hashOut) );
}
len = sArmorLine( (PGPByte *) passKey,
kPGPRecon_NumShares * kReconstructWrapKeySize,
(char *) szArmoredPassKey );
szArmoredPassKey[len] = '\0';
err = sGetCertserverLocation( ldap, szCertserverDN ); CKERR;
err = PGPNewLDAPMessage( ldap, &message ); CKERR;
if( IsNull( message ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
err = PGPGetKeyID( con->targetKey, &keyid ); CKERR;
err = PGPGetKeyIDString( &keyid, kPGPKeyIDString_Full, szKeyID ); CKERR;
dn = (char *)PGPNewData( con->memMgr,
strlen( kPGPReconCertIDAttr ) + sizeof( "=" ) + strlen( szKeyID ) +
sizeof( ", " ) + strlen( szCertserverDN ) + 1,
kPGPMemoryMgrFlags_Clear );
if( IsNull( dn ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
sprintf( dn, "%s=%s, %s", kPGPReconCertIDAttr, szKeyID + 2, szCertserverDN );
err = PGPldapBindSync( ldap, dn, szArmoredPassKey, kPGPldapAuth_Simple );CKERR;
attrs[0] = kPGPReconDataAttr;
attrs[1] = NULL;
err = PGPldapSearchSync( ldap,
dn,
kPGPldapScope_Base,
kPGPObjectclassAny,
attrs,
FALSE,
message );
if( err == kPGPError_LDAPNoSuchObject )
err = kPGPError_ItemNotFound;
CKERR;
err = PGPldapGetValuesLen( ldap, message, kPGPReconDataAttr, &berValues );CKERR;
if( IsNull( berValues ) )
{
err = kPGPError_ItemNotFound;
goto done;
}
con->blobDataSize = berValues[0]->length;
con->blobData = (PGPByte *)PGPNewSecureData( con->memMgr, con->blobDataSize,
kPGPMemoryMgrFlags_Clear );
if( IsNull( con->blobData ) )
{
con->blobDataSize = 0;
err = kPGPError_OutOfMemory;
goto done;
}
pgpCopyMemory( berValues[0]->value, con->blobData, con->blobDataSize );
}
*outReconData = (PGPByte *)PGPNewSecureData( con->memMgr,
con->blobDataSize, kPGPMemoryMgrFlags_Clear );
if( IsNull( *outReconData ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
pgpCopyMemory( con->blobData, *outReconData, con->blobDataSize );
*outReconSize = con->blobDataSize;
done:
if( PGPtlsContextRefIsValid( tlsContext ) )
(void) PGPFreeTLSContext( tlsContext );
if( PGPtlsSessionRefIsValid( tlsSession ) )
(void) PGPFreeTLSSession( tlsSession );
if( IsntNull( dn ) )
(void) PGPFreeData( dn );
if( IsntNull( lud ) )
(void) PGPFreeLDAPURLDesc( lud );
if( IsntNull( berValues ) )
(void) PGPFreeLDAPValuesLen( berValues );
if( PGPldapMessageRefIsValid( message ) )
(void) PGPFreeLDAPMessage( message );
if( PGPldapContextRefIsValid( ldap ) )
(void) PGPFreeLDAPContext( ldap );
if( PGPHashContextRefIsValid( hashCon ) )
(void) PGPFreeHashContext( hashCon );
return err;
}
PGPError
PGPReconstruct(
PGPReconContextRef reconRef,
PGPReconPasses inPassInfo,
PGPByte *inReconData,
PGPSize inReconDataSize,
PGPKeyDBRef *outReconstructedKey )
{
PGPError err = kPGPError_NoErr;
PGPReconContextPriv * con = (PGPReconContextPriv *)reconRef;
PGPByte zeroIV[kReconCipherBlockSize];
PGPByte *blockWalk;
PGPKeyID targetKeyID;
PGPUInt16 hashReps;
PGPUInt32 innerBlockPadLen,
innerBlockLen;
PGPByte *innerBlock = NULL;
PGPUInt16 matrixIndex[kPGPRecon_Threshold];
PGPUInt16 matrixIndex2[kPGPRecon_Threshold];
PGPUInt32 hashIndex,
shareIndex;
PGPByte passKey[kPGPRecon_NumShares][kReconstructWrapKeySize];
PGPByte shares[kPGPRecon_Threshold][kReconNaturalShareSize];
PGPSymmetricCipherContextRef symmCon = kInvalidPGPSymmetricCipherContextRef;
PGPCBCContextRef cbcCon = kInvalidPGPCBCContextRef;
PGPHashContextRef hashCon = kInvalidPGPHashContextRef;
PGPByte hashMagic[sizeof(PGPUInt32)];
PGPByte hashOut[20];
PGPByte shareOut[kReconShareSize];
PGPByte blockKey[kReconstructWrapKeySize];
*outReconstructedKey = kInvalidPGPKeyDBRef;
pgpClearMemory( zeroIV, kReconCipherBlockSize );
err = PGPNewHashContext( con->context,
kPGPHashAlgorithm_SHA, &hashCon ); CKERR;
blockWalk = inReconData;
if( inReconDataSize < kReconMinBlobSize )
{
err = kPGPError_KeyInvalid;
goto done;
}
err = PGPGetKeyID( con->targetKey, &targetKeyID ); CKERR;
if( PGPCompareKeyIDs( (PGPKeyID *)blockWalk, &targetKeyID ) )
{
err = kPGPError_KeyInvalid;
goto done;
}
blockWalk += sizeof(PGPKeyID) + sizeof(PGPReconPrompts);
hashReps = PGPEndianToUInt16( kPGPBigEndian, blockWalk );
/* Hash all 5 outer keys */
PGPUInt32ToEndian( kReconOuterMagic, kPGPBigEndian, hashMagic );
for( shareIndex = 0; shareIndex < kPGPRecon_NumShares; shareIndex++ )
{
for( hashIndex = 0; hashIndex < hashReps; hashIndex++ )
{
(void) PGPContinueHash( hashCon, inPassInfo[shareIndex],
strlen( inPassInfo[shareIndex] ) );
(void) PGPContinueHash( hashCon, hashMagic, sizeof(hashMagic) );
}
err = PGPFinalizeHash( hashCon, hashOut ); CKERR;
err = PGPResetHash( hashCon ); CKERR;
pgpCopyMemory( hashOut, passKey[shareIndex], kReconstructWrapKeySize );
pgpClearMemory( hashOut, sizeof(hashOut) );
}
/* Unwrap outer layer */
blockWalk = inReconData;
blockWalk += sizeof(PGPKeyID) + sizeof(PGPReconPrompts);
blockWalk += sizeof(PGPUInt16);
innerBlockPadLen = PGPEndianToUInt32( kPGPBigEndian, blockWalk );
blockWalk += sizeof(PGPUInt32);
err = PGPNewSymmetricCipherContext( con->context,
kPGPCipherAlgorithm_CAST5, &symmCon ); CKERR;
err = PGPNewCBCContext( symmCon, &cbcCon ); CKERR;
innerBlock = (PGPByte *)PGPNewSecureData( con->memMgr,
innerBlockPadLen, kPGPMemoryMgrFlags_Clear); CKERR;
/* Try all possible combinations of 3 keys against innerBlock */
/* Use only 3 so that some wrong answers don't penalize */
/* Going 6 levels deep, redented for readability... */
for( matrixIndex[0] = 0; matrixIndex[0] < kPGPRecon_NumShares; matrixIndex[0]++ )
{ for( matrixIndex[1] = 0; matrixIndex[1] < kPGPRecon_NumShares; matrixIndex[1]++ )
{ for( matrixIndex[2] = 0; matrixIndex[2] < kPGPRecon_NumShares; matrixIndex[2]++ )
{
if( ( matrixIndex[0] == matrixIndex[1] ) || ( matrixIndex[1] == matrixIndex[2] ) ||
( matrixIndex[2] == matrixIndex[0] ) )
continue;
for( matrixIndex2[0] = 0; matrixIndex2[0] < kPGPRecon_NumShares; matrixIndex2[0]++ )
{ for( matrixIndex2[1] = 0; matrixIndex2[1] < kPGPRecon_NumShares; matrixIndex2[1]++ )
{ for( matrixIndex2[2] = 0; matrixIndex2[2] < kPGPRecon_NumShares; matrixIndex2[2]++ )
{
if( ( matrixIndex2[0] == matrixIndex2[1] ) || ( matrixIndex2[1] == matrixIndex2[2] ) ||
( matrixIndex2[2] == matrixIndex2[0] ) )
continue;
for( shareIndex = 0; shareIndex < kPGPRecon_Threshold; shareIndex++ )
{
err = PGPInitCBC( cbcCon, passKey[matrixIndex[shareIndex]], zeroIV ); CKERR;
err = PGPCBCDecrypt( cbcCon, blockWalk +
kReconShareSize * matrixIndex2[shareIndex],
kReconShareSize, shareOut ); CKERR;
pgpCopyMemory( shareOut, shares[shareIndex], kReconNaturalShareSize );
}
if( ( shares[0][0] != kPGPShare_Version1 ) ||
( shares[1][0] != kPGPShare_Version1 ) ||
( shares[2][0] != kPGPShare_Version1 ) )
continue;
err = PGPSecretReconstructData( con->context, shares,
kReconstructWrapKeySize, kPGPRecon_Threshold, blockKey );
if( IsPGPError( err ) )
{
err = kPGPError_NoErr;
continue;
}
err = PGPInitCBC( cbcCon, blockKey, zeroIV ); CKERR;
err = PGPCBCDecrypt( cbcCon, blockWalk + kReconShareSize * kPGPRecon_NumShares,
innerBlockPadLen, innerBlock ); CKERR;
if( !PGPCompareKeyIDs( (PGPKeyID *)innerBlock, &targetKeyID ) )
{
/* Outer layer has been removed */
goto foundCombo;
}
}}}}}}
err = kPGPError_BadPassphrase;
goto done;
foundCombo:
/* Unwrap inner layer */
blockWalk = innerBlock + sizeof(PGPKeyID);
if( hashReps != PGPEndianToUInt16( kPGPBigEndian, blockWalk ) )
{
err = kPGPError_BadPassphrase;
goto done;
}
blockWalk += sizeof(PGPUInt16);
/* Hash all 5 inner keys */
PGPUInt32ToEndian( kReconInnerMagic, kPGPBigEndian, hashMagic );
for( shareIndex = 0; shareIndex < kPGPRecon_NumShares; shareIndex++ )
{
for( hashIndex = 0; hashIndex < hashReps; hashIndex++ )
{
(void) PGPContinueHash( hashCon, inPassInfo[shareIndex],
strlen( inPassInfo[shareIndex] ) );
(void) PGPContinueHash( hashCon, hashMagic, sizeof(hashMagic) );
}
err = PGPFinalizeHash( hashCon, hashOut ); CKERR;
err = PGPResetHash( hashCon ); CKERR;
pgpCopyMemory( hashOut, passKey[shareIndex], kReconstructWrapKeySize );
pgpClearMemory( hashOut, sizeof(hashOut) );
}
/* Decrypt the shares */
for( shareIndex = 0; shareIndex < kPGPRecon_Threshold; shareIndex++ )
{
err = PGPInitCBC( cbcCon, passKey[matrixIndex[shareIndex]], zeroIV ); CKERR;
err = PGPCBCDecrypt( cbcCon, blockWalk +
kReconShareSize * matrixIndex2[shareIndex],
kReconShareSize, shareOut ); CKERR;
pgpCopyMemory( shareOut, shares[shareIndex], kReconNaturalShareSize );
}
err = PGPSecretReconstructData( con->context, shares,
kReconstructWrapKeySize, kPGPRecon_Threshold, blockKey );
if( IsPGPError( err ) )
{
err = kPGPError_BadPassphrase;
goto done;
}
blockWalk += kReconShareSize * kPGPRecon_NumShares;
innerBlockPadLen -= sizeof(PGPKeyID) + sizeof(PGPUInt16) +
kReconShareSize * kPGPRecon_NumShares;
while( innerBlockPadLen % kReconCipherBlockSize )
innerBlockPadLen--;
err = PGPInitCBC( cbcCon, blockKey, zeroIV ); CKERR;
err = PGPCBCDecrypt( cbcCon, blockWalk, innerBlockPadLen, blockWalk ); CKERR;
innerBlockLen = PGPEndianToUInt32( kPGPBigEndian, blockWalk );
blockWalk += sizeof(PGPUInt32);
if( innerBlockLen > innerBlockPadLen )
{
err = kPGPError_CorruptData;
goto done;
}
/* Import private key */
err = PGPImport( con->context, outReconstructedKey,
PGPOInputBuffer( con->context, blockWalk, innerBlockLen ),
PGPOLastOption( con->context ) ); CKERR;
done:
pgpClearMemory( blockKey, sizeof(blockKey) );
pgpClearMemory( passKey, sizeof(passKey) );
pgpClearMemory( shares, sizeof(shares) );
if( IsntNull( innerBlock ) )
(void) PGPFreeData( innerBlock );
if( PGPCBCContextRefIsValid( cbcCon ) )
(void) PGPFreeCBCContext( cbcCon );
if( PGPHashContextRefIsValid( hashCon ) )
(void) PGPFreeHashContext( hashCon );
return err;
}
#ifdef PGP_CMDLINE
PGPError
PGPSetReconstructionServerURL(
PGPReconContextRef reconRef,
char *pszServerURL,
PGPUInt32 dwServerType )
{
PGPError err = kPGPError_NoErr;
PGPReconContextPriv * con = (PGPReconContextPriv *)reconRef;
PGPValidatePtr( reconRef );
strcpy(con->szServerURL, pszServerURL);
con->serverType = dwServerType;
return err;
}
#endif /* PGP_CMDLINE */
/*__Editor_settings____
Local Variables:
tab-width: 4
End:
vi: ts=4 sw=4
vim: si
_____________________*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -