void CryptData::SetKey50(bool Encrypt,SecPassword *Password,const wchar *PwdW, const byte *Salt,const byte *InitV,uint Lg2Cnt,byte *HashKey, byte *PswCheck) { if (Lg2Cnt>CRYPT5_KDF_LG2_COUNT_MAX) return; byte Key[32],PswCheckValue[SHA256_DIGEST_SIZE],HashKeyValue[SHA256_DIGEST_SIZE]; bool Found=false; for (uint I=0;I<ASIZE(KDFCache);I++) { KDFCacheItem *Item=KDFCache+I; if (Item->Lg2Count==Lg2Cnt && Item->Pwd==*Password && memcmp(Item->Salt,Salt,SIZE_SALT50)==0) { SecHideData(Item->Key,sizeof(Item->Key),false); memcpy(Key,Item->Key,sizeof(Key)); SecHideData(Item->Key,sizeof(Item->Key),true); memcpy(PswCheckValue,Item->PswCheckValue,sizeof(PswCheckValue)); memcpy(HashKeyValue,Item->HashKeyValue,sizeof(HashKeyValue)); Found=true; break; } } if (!Found) { char PwdUtf[MAXPASSWORD*4]; WideToUtf(PwdW,PwdUtf,ASIZE(PwdUtf)); pbkdf2((byte *)PwdUtf,strlen(PwdUtf),Salt,SIZE_SALT50,Key,HashKeyValue,PswCheckValue,(1<<Lg2Cnt)); cleandata(PwdUtf,sizeof(PwdUtf)); KDFCacheItem *Item=KDFCache+(KDFCachePos++ % ASIZE(KDFCache)); Item->Lg2Count=Lg2Cnt; Item->Pwd=*Password; memcpy(Item->Salt,Salt,SIZE_SALT50); memcpy(Item->Key,Key,sizeof(Key)); memcpy(Item->PswCheckValue,PswCheckValue,sizeof(PswCheckValue)); memcpy(Item->HashKeyValue,HashKeyValue,sizeof(HashKeyValue)); SecHideData(Item->Key,sizeof(Key),true); } if (HashKey!=NULL) memcpy(HashKey,HashKeyValue,SHA256_DIGEST_SIZE); if (PswCheck!=NULL) { memset(PswCheck,0,SIZE_PSWCHECK); for (uint I=0;I<SHA256_DIGEST_SIZE;I++) PswCheck[I%SIZE_PSWCHECK]^=PswCheckValue[I]; cleandata(PswCheckValue,sizeof(PswCheckValue)); } // NULL initialization vector is possible if we only need the password // check value for archive encryption header. if (InitV!=NULL) rin.Init(Encrypt, Key, 256, InitV); cleandata(Key,sizeof(Key)); }
// We got a complain from user that it is possible to create WinRAR dump // with "Create dump file" command in Windows Task Manager and then easily // locate Unicode password string in the dump. It is unsecure if several // people share the same computer and somebody left WinRAR copy with entered // password. So we decided to obfuscate the password to make it more difficult // to find it in dump. void SecPassword::Process(const wchar *Src,size_t SrcSize,wchar *Dst,size_t DstSize,bool Encode) { // Source string can be shorter than destination as in case when we process // -p<pwd> parameter, so we need to take into account both sizes. memcpy(Dst,Src,Min(SrcSize,DstSize)*sizeof(*Dst)); SecHideData(Dst,DstSize*sizeof(*Dst),Encode,CrossProcess); }