"Fossies" - the Fresh Open Source Software Archive

Member "unrar/crypt5.cpp" (4 May 2022, 8021 Bytes) of package /linux/misc/unrarsrc-6.1.7.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "crypt5.cpp" see the Fossies "Dox" file reference documentation.

    1 static void hmac_sha256(const byte *Key,size_t KeyLength,const byte *Data,
    2                         size_t DataLength,byte *ResDigest,
    3                         sha256_context *ICtxOpt,bool *SetIOpt,
    4                         sha256_context *RCtxOpt,bool *SetROpt)
    5 {
    6   const size_t Sha256BlockSize=64; // As defined in RFC 4868.
    7 
    8   byte KeyHash[SHA256_DIGEST_SIZE];
    9   if (KeyLength > Sha256BlockSize) // Convert longer keys to key hash.
   10   {
   11     sha256_context KCtx;
   12     sha256_init(&KCtx);
   13     sha256_process(&KCtx, Key, KeyLength);
   14     sha256_done(&KCtx, KeyHash);
   15 
   16     Key = KeyHash;
   17     KeyLength = SHA256_DIGEST_SIZE;
   18   }
   19 
   20   byte KeyBuf[Sha256BlockSize]; // Store the padded key here.
   21   sha256_context ICtx;
   22 
   23   if (ICtxOpt!=NULL && *SetIOpt)
   24     ICtx=*ICtxOpt; // Use already calculated first block context.
   25   else
   26   {
   27     // This calculation is the same for all iterations with same password.
   28     // So for PBKDF2 we can calculate it only for first block and then reuse
   29     // to improve performance. 
   30 
   31     for (size_t I = 0; I < KeyLength; I++) // Use 0x36 padding for inner digest.
   32       KeyBuf[I] = Key[I] ^ 0x36;
   33     for (size_t I = KeyLength; I < Sha256BlockSize; I++)
   34       KeyBuf[I] = 0x36;
   35 
   36     sha256_init(&ICtx);
   37     sha256_process(&ICtx, KeyBuf, Sha256BlockSize); // Hash padded key.
   38   }
   39 
   40   if (ICtxOpt!=NULL && !*SetIOpt) // Store constant context for further reuse.
   41   {
   42     *ICtxOpt=ICtx;
   43     *SetIOpt=true;
   44   }
   45 
   46   sha256_process(&ICtx, Data, DataLength); // Hash data.
   47 
   48   byte IDig[SHA256_DIGEST_SIZE]; // Internal digest for padded key and data.
   49   sha256_done(&ICtx, IDig);
   50 
   51   sha256_context RCtx;
   52 
   53   if (RCtxOpt!=NULL && *SetROpt)
   54     RCtx=*RCtxOpt; // Use already calculated first block context.
   55   else
   56   {
   57     // This calculation is the same for all iterations with same password.
   58     // So for PBKDF2 we can calculate it only for first block and then reuse
   59     // to improve performance. 
   60 
   61     for (size_t I = 0; I < KeyLength; I++) // Use 0x5c for outer key padding.
   62       KeyBuf[I] = Key[I] ^ 0x5c;
   63     for (size_t I = KeyLength; I < Sha256BlockSize; I++)
   64       KeyBuf[I] = 0x5c;
   65 
   66     sha256_init(&RCtx);
   67     sha256_process(&RCtx, KeyBuf, Sha256BlockSize); // Hash padded key.
   68   }
   69 
   70   if (RCtxOpt!=NULL && !*SetROpt) // Store constant context for further reuse.
   71   {
   72     *RCtxOpt=RCtx;
   73     *SetROpt=true;
   74   }
   75 
   76   sha256_process(&RCtx, IDig, SHA256_DIGEST_SIZE); // Hash internal digest.
   77 
   78   sha256_done(&RCtx, ResDigest);
   79 }
   80 
   81 
   82 // PBKDF2 for 32 byte key length. We generate the key for specified number
   83 // of iteration count also as two supplementary values (key for checksums
   84 // and password verification) for iterations+16 and iterations+32.
   85 void pbkdf2(const byte *Pwd, size_t PwdLength, 
   86             const byte *Salt, size_t SaltLength,
   87             byte *Key, byte *V1, byte *V2, uint Count)
   88 {
   89   const size_t MaxSalt=64;
   90   byte SaltData[MaxSalt+4];
   91   memcpy(SaltData, Salt, Min(SaltLength,MaxSalt));
   92 
   93   SaltData[SaltLength + 0] = 0; // Salt concatenated to 1.
   94   SaltData[SaltLength + 1] = 0;
   95   SaltData[SaltLength + 2] = 0;
   96   SaltData[SaltLength + 3] = 1;
   97 
   98   // First iteration: HMAC of password, salt and block index (1).
   99   byte U1[SHA256_DIGEST_SIZE];
  100   hmac_sha256(Pwd, PwdLength, SaltData, SaltLength + 4, U1, NULL, NULL, NULL, NULL);
  101   byte Fn[SHA256_DIGEST_SIZE]; // Current function value.
  102   memcpy(Fn, U1, sizeof(Fn)); // Function at first iteration.
  103 
  104   uint  CurCount[] = { Count-1, 16, 16 };
  105   byte *CurValue[] = { Key    , V1, V2 };
  106   
  107   sha256_context ICtxOpt,RCtxOpt;
  108   bool SetIOpt=false,SetROpt=false;
  109   
  110   byte U2[SHA256_DIGEST_SIZE];
  111   for (uint I = 0; I < 3; I++) // For output key and 2 supplementary values.
  112   {
  113     for (uint J = 0; J < CurCount[I]; J++) 
  114     {
  115       // U2 = PRF (P, U1).
  116       hmac_sha256(Pwd, PwdLength, U1, sizeof(U1), U2, &ICtxOpt, &SetIOpt, &RCtxOpt, &SetROpt);
  117       memcpy(U1, U2, sizeof(U1));
  118       for (uint K = 0; K < sizeof(Fn); K++) // Function ^= U.
  119         Fn[K] ^= U1[K];
  120     }
  121     memcpy(CurValue[I], Fn, SHA256_DIGEST_SIZE);
  122   }
  123 
  124   cleandata(SaltData, sizeof(SaltData));
  125   cleandata(Fn, sizeof(Fn));
  126   cleandata(U1, sizeof(U1));
  127   cleandata(U2, sizeof(U2));
  128 }
  129 
  130 
  131 void CryptData::SetKey50(bool Encrypt,SecPassword *Password,const wchar *PwdW,
  132      const byte *Salt,const byte *InitV,uint Lg2Cnt,byte *HashKey,
  133      byte *PswCheck)
  134 {
  135   if (Lg2Cnt>CRYPT5_KDF_LG2_COUNT_MAX)
  136     return;
  137 
  138   byte Key[32],PswCheckValue[SHA256_DIGEST_SIZE],HashKeyValue[SHA256_DIGEST_SIZE];
  139   bool Found=false;
  140   for (uint I=0;I<ASIZE(KDF5Cache);I++)
  141   {
  142     KDF5CacheItem *Item=KDF5Cache+I;
  143     if (Item->Lg2Count==Lg2Cnt && Item->Pwd==*Password &&
  144         memcmp(Item->Salt,Salt,SIZE_SALT50)==0)
  145     {
  146       memcpy(Key,Item->Key,sizeof(Key));
  147       SecHideData(Key,sizeof(Key),false,false);
  148 
  149       memcpy(PswCheckValue,Item->PswCheckValue,sizeof(PswCheckValue));
  150       memcpy(HashKeyValue,Item->HashKeyValue,sizeof(HashKeyValue));
  151       Found=true;
  152       break;
  153     }
  154   }
  155 
  156   if (!Found)
  157   {
  158     char PwdUtf[MAXPASSWORD*4];
  159     WideToUtf(PwdW,PwdUtf,ASIZE(PwdUtf));
  160     
  161     pbkdf2((byte *)PwdUtf,strlen(PwdUtf),Salt,SIZE_SALT50,Key,HashKeyValue,PswCheckValue,(1<<Lg2Cnt));
  162     cleandata(PwdUtf,sizeof(PwdUtf));
  163 
  164     KDF5CacheItem *Item=KDF5Cache+(KDF5CachePos++ % ASIZE(KDF5Cache));
  165     Item->Lg2Count=Lg2Cnt;
  166     Item->Pwd=*Password;
  167     memcpy(Item->Salt,Salt,SIZE_SALT50);
  168     memcpy(Item->Key,Key,sizeof(Item->Key));
  169     memcpy(Item->PswCheckValue,PswCheckValue,sizeof(PswCheckValue));
  170     memcpy(Item->HashKeyValue,HashKeyValue,sizeof(HashKeyValue));
  171     SecHideData(Item->Key,sizeof(Item->Key),true,false);
  172   }
  173   if (HashKey!=NULL)
  174     memcpy(HashKey,HashKeyValue,SHA256_DIGEST_SIZE);
  175   if (PswCheck!=NULL)
  176   {
  177     memset(PswCheck,0,SIZE_PSWCHECK);
  178     for (uint I=0;I<SHA256_DIGEST_SIZE;I++)
  179       PswCheck[I%SIZE_PSWCHECK]^=PswCheckValue[I];
  180     cleandata(PswCheckValue,sizeof(PswCheckValue));
  181   }
  182 
  183   // NULL initialization vector is possible if we only need the password
  184   // check value for archive encryption header.
  185   if (InitV!=NULL)
  186     rin.Init(Encrypt, Key, 256, InitV);
  187 
  188   cleandata(Key,sizeof(Key));
  189 }
  190 
  191 
  192 void ConvertHashToMAC(HashValue *Value,byte *Key)
  193 {
  194   if (Value->Type==HASH_CRC32)
  195   {
  196     byte RawCRC[4];
  197     RawPut4(Value->CRC32,RawCRC);
  198     byte Digest[SHA256_DIGEST_SIZE];
  199     hmac_sha256(Key,SHA256_DIGEST_SIZE,RawCRC,sizeof(RawCRC),Digest,NULL,NULL,NULL,NULL);
  200     Value->CRC32=0;
  201     for (uint I=0;I<ASIZE(Digest);I++)
  202       Value->CRC32^=Digest[I] << ((I & 3) * 8);
  203   }
  204   if (Value->Type==HASH_BLAKE2)
  205   {
  206     byte Digest[BLAKE2_DIGEST_SIZE];
  207     hmac_sha256(Key,BLAKE2_DIGEST_SIZE,Value->Digest,sizeof(Value->Digest),Digest,NULL,NULL,NULL,NULL);
  208     memcpy(Value->Digest,Digest,sizeof(Value->Digest));
  209   }
  210 }
  211 
  212 
  213 #if 0
  214 static void TestPBKDF2();
  215 struct TestKDF {TestKDF() {TestPBKDF2();exit(0);}} GlobalTestKDF;
  216 
  217 void TestPBKDF2() // Test PBKDF2 HMAC-SHA256
  218 {
  219   byte Key[32],V1[32],V2[32];
  220 
  221   pbkdf2((byte *)"password", 8, (byte *)"salt", 4, Key, V1, V2, 1);
  222   byte Res1[32]={0x12, 0x0f, 0xb6, 0xcf, 0xfc, 0xf8, 0xb3, 0x2c, 0x43, 0xe7, 0x22, 0x52, 0x56, 0xc4, 0xf8, 0x37, 0xa8, 0x65, 0x48, 0xc9, 0x2c, 0xcc, 0x35, 0x48, 0x08, 0x05, 0x98, 0x7c, 0xb7, 0x0b, 0xe1, 0x7b };
  223   mprintf(L"\nPBKDF2 test1: %s", memcmp(Key,Res1,32)==0 ? L"OK":L"Failed");
  224 
  225   pbkdf2((byte *)"password", 8, (byte *)"salt", 4, Key, V1, V2, 4096);
  226   byte Res2[32]={0xc5, 0xe4, 0x78, 0xd5, 0x92, 0x88, 0xc8, 0x41, 0xaa, 0x53, 0x0d, 0xb6, 0x84, 0x5c, 0x4c, 0x8d, 0x96, 0x28, 0x93, 0xa0, 0x01, 0xce, 0x4e, 0x11, 0xa4, 0x96, 0x38, 0x73, 0xaa, 0x98, 0x13, 0x4a };
  227   mprintf(L"\nPBKDF2 test2: %s", memcmp(Key,Res2,32)==0 ? L"OK":L"Failed");
  228 
  229   pbkdf2((byte *)"just some long string pretending to be a password", 49, (byte *)"salt, salt, salt, a lot of salt", 31, Key, V1, V2, 65536);
  230   byte Res3[32]={0x08, 0x0f, 0xa3, 0x1d, 0x42, 0x2d, 0xb0, 0x47, 0x83, 0x9b, 0xce, 0x3a, 0x3b, 0xce, 0x49, 0x51, 0xe2, 0x62, 0xb9, 0xff, 0x76, 0x2f, 0x57, 0xe9, 0xc4, 0x71, 0x96, 0xce, 0x4b, 0x6b, 0x6e, 0xbf};
  231   mprintf(L"\nPBKDF2 test3: %s", memcmp(Key,Res3,32)==0 ? L"OK":L"Failed");
  232 }
  233 #endif