| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 | 
							- //---------------------------------------------------------------------------
 
- #include <vcl.h>
 
- #pragma hdrstop
 
- #ifdef USE_COMPATIBLE_THREAD
 
- // CompThread.pas must be linked to project
 
- #include <CompThread.hpp>
 
- #define THREAD_CLASS TCompThread
 
- #else
 
- #include <Classes.hpp>
 
- #define THREAD_CLASS TThread
 
- #endif
 
- #include <Common.h>
 
- #include "TextsCore.h"
 
- #include <PuttyIntf.h>
 
- #include "KeyGen.h"
 
- //---------------------------------------------------------------------------
 
- #pragma package(smart_init)
 
- //---------------------------------------------------------------------------
 
- extern "C" void KeyGenerationProgressUpdate(void * Thread,
 
-     int Action, int Phase, int IProgress);
 
- //---------------------------------------------------------------------------
 
- class TKeyGenerationThread : public THREAD_CLASS
 
- {
 
- public:
 
-   #define PROGRESSRANGE 65535
 
-   #define MAXPHASE 5
 
-   struct
 
-   {
 
-     int NPhases;
 
-     struct
 
-     {
 
-       bool Exponential;
 
-       unsigned StartPoint, Total;
 
-       unsigned Param, Current, N;   /* if exponential */
 
-       unsigned Mult;                    /* if linear */
 
-     } Phases[MAXPHASE];
 
-     unsigned Total, Divisor, Range;
 
-     unsigned Position;
 
-     TKeyGenerationComplete Complete;
 
-   } Progress;
 
-   TKeyGenerator * FGenerator;
 
-   __fastcall TKeyGenerationThread(TKeyGenerator * AGenerator):
 
-     THREAD_CLASS(true)
 
-   {
 
-     FGenerator = AGenerator;
 
-     Resume();
 
-   }
 
-   void __fastcall DistributeProgressUpdate()
 
-   {
 
-     FGenerator->ProgressUpdate(Progress.Range, Progress.Position, Progress.Complete);
 
-   }
 
-   void __fastcall ProgressUpdate(int Action, int Phase, unsigned IProgress)
 
-   {
 
-     int Position;
 
-     if (Action < PROGFN_READY && Progress.NPhases < Phase)
 
-         Progress.NPhases = Phase;
 
-     switch (Action)
 
-     {
 
-       case PROGFN_INITIALISE:
 
-         Progress.NPhases = 0;
 
-         Progress.Complete = kgInProgress;
 
-         break;
 
-       case PROGFN_LIN_PHASE:
 
-         Progress.Phases[Phase-1].Exponential = false;
 
-         Progress.Phases[Phase-1].Mult = Progress.Phases[Phase].Total / IProgress;
 
-         break;
 
-       case PROGFN_EXP_PHASE:
 
-         Progress.Phases[Phase-1].Exponential = true;
 
-         Progress.Phases[Phase-1].Param = 0x10000 + IProgress;
 
-         Progress.Phases[Phase-1].Current = Progress.Phases[Phase-1].Total;
 
-         Progress.Phases[Phase-1].N = 0;
 
-         break;
 
-       case PROGFN_PHASE_EXTENT:
 
-         Progress.Phases[Phase-1].Total = IProgress;
 
-         break;
 
-       case PROGFN_READY:
 
-         {
 
-           unsigned Total = 0;
 
-           int i;
 
-           for (i = 0; i < Progress.NPhases; i++)
 
-           {
 
-             Progress.Phases[i].StartPoint = Total;
 
-             Total += Progress.Phases[i].Total;
 
-           }
 
-           Progress.Total = Total;
 
-           Progress.Divisor = ((Progress.Total + PROGRESSRANGE - 1) / PROGRESSRANGE);
 
-           Progress.Range = Progress.Total / Progress.Divisor;
 
-           Synchronize(DistributeProgressUpdate);
 
-         }
 
-         break;
 
-       case PROGFN_PROGRESS:
 
-         if (Progress.Phases[Phase-1].Exponential)
 
-         {
 
-           while (Progress.Phases[Phase-1].N < IProgress)
 
-           {
 
-             Progress.Phases[Phase-1].N++;
 
-             Progress.Phases[Phase-1].Current *= Progress.Phases[Phase-1].Param;
 
-             Progress.Phases[Phase-1].Current /= 0x10000;
 
-           }
 
-           Position = (Progress.Phases[Phase-1].StartPoint +
 
-             Progress.Phases[Phase-1].Total - Progress.Phases[Phase-1].Current);
 
-         }
 
-         else
 
-         {
 
-           Position = (Progress.Phases[Phase-1].StartPoint +
 
-             IProgress * Progress.Phases[Phase-1].Mult);
 
-         }
 
-         Progress.Position = Position / Progress.Divisor;
 
-         Synchronize(DistributeProgressUpdate);
 
-         break;
 
-     }
 
-   }
 
-   virtual void __fastcall Execute()
 
-   {
 
-     try
 
-     {
 
-       ProgressUpdate(PROGFN_INITIALISE, 0, 0);
 
-       if (FGenerator->KeyType == ktDSA)
 
-       {
 
-         dsa_generate(FGenerator->FDSSKey, FGenerator->KeySize,
 
-           KeyGenerationProgressUpdate, this);
 
-       }
 
-       else
 
-       {
 
-         rsa_generate(FGenerator->FRSAKey, FGenerator->KeySize,
 
-           KeyGenerationProgressUpdate, this);
 
-       }
 
-       Progress.Complete = kgSuccess;
 
-     }
 
-     catch(...)
 
-     {
 
-       Progress.Complete = kgFailure;
 
-     }
 
-     Synchronize(DistributeProgressUpdate);
 
-   }
 
- #pragma warn +lvc
 
- };
 
- //---------------------------------------------------------------------------
 
- void KeyGenerationProgressUpdate(void * Thread,
 
-   int Action, int Phase, int IProgress)
 
- {
 
-   DebugAssert(Thread);
 
-   ((TKeyGenerationThread*)Thread)->ProgressUpdate(Action, Phase, IProgress);
 
- }
 
- //---------------------------------------------------------------------------
 
- __fastcall TKeyGenerator::TKeyGenerator():
 
-   TObject()
 
- {
 
-   FSSH2Key = new ssh2_userkey;
 
-   FRSAKey = new RSAKey;
 
-   FDSSKey = new dss_key;
 
-   FEntropy = NULL;
 
-   FState = kgInitializing;
 
-   FOnGenerating = NULL;
 
-   FGenerationRange = -1;
 
-   KeyType = ktRSA2;
 
-   KeySize = 1024;
 
- }
 
- //---------------------------------------------------------------------------
 
- __fastcall TKeyGenerator::~TKeyGenerator()
 
- {
 
-   DebugAssert(FState != kgGenerating);
 
-   if (FEntropy) delete FEntropy;
 
-   delete FSSH2Key;
 
-   delete FRSAKey;
 
-   delete FDSSKey;
 
- }
 
- //---------------------------------------------------------------------------
 
- void __fastcall TKeyGenerator::SetKeySize(int value)
 
- {
 
-   DebugAssert(FState != kgGenerating);
 
-   FState = kgInitializing;
 
-   FKeySize = value;
 
-   FEntropyRequired = (KeySize / 2) * 2;
 
-   FEntropyGot = 0;
 
-   if (FEntropy) delete FEntropy;
 
-   FEntropy = new TEntropyBit[FEntropyRequired];
 
- }
 
- //---------------------------------------------------------------------------
 
- void __fastcall TKeyGenerator::SetKeyType(TKeyType value)
 
- {
 
-   DebugAssert(FState != kgGenerating);
 
-   FState = kgInitializing;
 
-   FKeyType = value;
 
- }
 
- //---------------------------------------------------------------------------
 
- void __fastcall TKeyGenerator::AddEntropy(TEntropyBit Entropy)
 
- {
 
-   DebugAssert(FState == kgInitializing);
 
-   DebugAssert(FEntropy);
 
-   DebugAssert(FEntropyGot < FEntropyRequired);
 
-   FEntropy[FEntropyGot++] = Entropy;
 
-   if (FEntropyGot == FEntropyRequired)
 
-   {
 
-     FState = kgInitialized;
 
-     random_add_heavynoise(FEntropy, FEntropyRequired * sizeof(TEntropyBit));
 
-     delete FEntropy;
 
-     FEntropy = NULL;
 
-   }
 
- }
 
- //---------------------------------------------------------------------------
 
- void __fastcall TKeyGenerator::ResetKey()
 
- {
 
-   DebugAssert(FSSH2Key);
 
-   switch (KeyType) {
 
-     case ktDSA:
 
-       FSSH2Key->data = FDSSKey;
 
-       FSSH2Key->alg = &ssh_dss;
 
-       break;
 
-     case ktRSA2:
 
-       FSSH2Key->data = FRSAKey;
 
-       FSSH2Key->alg = &ssh_rsa;
 
-       break;
 
-   }
 
-   FFingerprint = "";
 
-   FPublicKey = "";
 
-   if (Comment.IsEmpty())
 
-   {
 
-     Comment = FORMAT("%s-key-%s",
 
-       ((KeyType == ktDSA ? "dsa" : "rsa"), FormatDateTime("yyyymmdd", Now())));
 
-   }
 
- }
 
- //---------------------------------------------------------------------------
 
- void __fastcall TKeyGenerator::StartGenerationThread()
 
- {
 
-   DebugAssert(FState == kgInitialized);
 
-   FState = kgGenerating;
 
-   new TKeyGenerationThread(this);
 
- }
 
- //---------------------------------------------------------------------------
 
- void __fastcall TKeyGenerator::Generate()
 
- {
 
-   DebugAssert(FState == kgInitialized);
 
-   THREAD_CLASS * Thread;
 
-   FState = kgGenerating;
 
-   Thread = new TKeyGenerationThread(this);
 
-   Thread->WaitFor();
 
- }
 
- //---------------------------------------------------------------------------
 
- void __fastcall TKeyGenerator::ProgressUpdate(int Range, int Position,
 
-   TKeyGenerationComplete Complete)
 
- {
 
-   DebugAssert(FState == kgGenerating);
 
-   if (Complete == kgSuccess)
 
-   {
 
-     FState = kgComplete;
 
-     ResetKey();
 
-   }
 
-   FGenerationRange = Range;
 
-   FGenerationPosition = Position;
 
-   if (FOnGenerating) FOnGenerating(this, Range, Position, Complete);
 
- }
 
- //---------------------------------------------------------------------------
 
- int __fastcall TKeyGenerator::GetPercentGenerated()
 
- {
 
-   switch (FState) {
 
-     case kgComplete: return 100;
 
-     case kgGenerating: return (FGenerationPosition * 100) / FGenerationRange;
 
-     default: return 0;
 
-   }
 
- }
 
- //---------------------------------------------------------------------------
 
- void __fastcall TKeyGenerator::SetComment(AnsiString value)
 
- {
 
-   if (FComment != value)
 
-   {
 
-     FComment = value;
 
-     FPublicKey = "";
 
-     DebugAssert(FSSH2Key);
 
-     FSSH2Key->comment = FComment.c_str();
 
-     FRSAKey->comment = FComment.c_str();
 
-   }
 
- }
 
- //---------------------------------------------------------------------------
 
- AnsiString __fastcall TKeyGenerator::GetFingerprint()
 
- {
 
-   if (FFingerprint.IsEmpty())
 
-   {
 
-     if (IsSSH2)
 
-     {
 
-       DebugAssert(FSSH2Key);
 
-       FFingerprint = FSSH2Key->alg->fingerprint(FSSH2Key->data);
 
-     }
 
-     else
 
-     {
 
-       char Buf[128];
 
-       rsa_fingerprint(Buf, sizeof(Buf), FRSAKey);
 
-       FFingerprint = Buf;
 
-     }
 
-   }
 
-   return FFingerprint;
 
- }
 
- //---------------------------------------------------------------------------
 
- bool __fastcall TKeyGenerator::GetIsSSH2()
 
- {
 
-   return (KeyType == ktDSA || KeyType == ktRSA2);
 
- }
 
- //---------------------------------------------------------------------------
 
- AnsiString __fastcall TKeyGenerator::GetPublicKey()
 
- {
 
-   if (FPublicKey.IsEmpty())
 
-   {
 
-     unsigned char *pub_blob;
 
-     char *buffer, *p;
 
-     int pub_len;
 
-     int i;
 
-     DebugAssert(FSSH2Key);
 
-     pub_blob = FSSH2Key->alg->public_blob(FSSH2Key->data, &pub_len);
 
-     buffer = new char[4 * ((pub_len + 2) / 3) + 1];
 
-     p = buffer;
 
-     i = 0;
 
-     while (i < pub_len)
 
-     {
 
-       int n = (pub_len - i < 3 ? pub_len - i : 3);
 
-       base64_encode_atom(pub_blob + i, n, p);
 
-       i += n;
 
-       p += 4;
 
-     }
 
-     *p = '\0';
 
-     FPublicKey = buffer;
 
-     sfree(pub_blob);
 
-     delete [] buffer;
 
-   }
 
-   return FPublicKey;
 
- }
 
- //---------------------------------------------------------------------------
 
- AnsiString __fastcall TKeyGenerator::GetAuthorizedKeysLine()
 
- {
 
-   DebugAssert(FSSH2Key);
 
-   return FORMAT("%s %s %s", (FSSH2Key->alg->name, PublicKey, Comment));
 
- }
 
- //---------------------------------------------------------------------------
 
- void __fastcall TKeyGenerator::SaveKey(const AnsiString FileName,
 
-   const AnsiString Passphrase, TKeyFormat Format)
 
- {
 
-   DebugAssert(FSSH2Key);
 
-   DebugAssert(FState == kgComplete);
 
-   DebugAssert((Format != kfOpenSSH && Format != kfSSHCom) || IsSSH2);
 
-   int Result;
 
-   if (IsSSH2)
 
-   {
 
-     switch (Format)
 
-     {
 
-       case kfPutty:
 
-         Result = ssh2_save_userkey(FileName.c_str(), FSSH2Key,
 
-           (char*)Passphrase.data());
 
-         break;
 
-       case kfOpenSSH:
 
-         Result = export_ssh2(FileName.c_str(), SSH_KEYTYPE_OPENSSH, FSSH2Key,
 
-           (char*)Passphrase.data());
 
-         break;
 
-       case kfSSHCom:
 
-         Result = export_ssh2(FileName.c_str(), SSH_KEYTYPE_SSHCOM, FSSH2Key,
 
-           (char*)Passphrase.data());
 
-         break;
 
-       default:
 
-         DebugFail();
 
-     }
 
-   }
 
-   else
 
-   {
 
-     DebugAssert(Format == kfPutty);
 
-     Result = saversakey(FileName.c_str(), FRSAKey,
 
-       (char*)Passphrase.data());
 
-   }
 
-   if (Result <= 0)
 
-     throw Exception(FMTLOAD(SAVE_KEY_ERROR, (FileName)));
 
- }
 
 
  |