summaryrefslogtreecommitdiff
path: root/unrar/unrar/crypt.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'unrar/unrar/crypt.hpp')
-rw-r--r--unrar/unrar/crypt.hpp191
1 files changed, 150 insertions, 41 deletions
diff --git a/unrar/unrar/crypt.hpp b/unrar/unrar/crypt.hpp
index e70aaa3..9dc0215 100644
--- a/unrar/unrar/crypt.hpp
+++ b/unrar/unrar/crypt.hpp
@@ -1,62 +1,171 @@
#ifndef _RAR_CRYPT_
#define _RAR_CRYPT_
-enum { OLD_DECODE=0,OLD_ENCODE=1,NEW_CRYPT=2 };
+enum CRYPT_METHOD {
+ CRYPT_NONE,CRYPT_RAR13,CRYPT_RAR15,CRYPT_RAR20,CRYPT_RAR30,CRYPT_RAR50
+};
+
+#define SIZE_SALT50 16
+#define SIZE_SALT30 8
+#define SIZE_INITV 16
+#define SIZE_PSWCHECK 8
+#define SIZE_PSWCHECK_CSUM 4
+
+#define CRYPT_BLOCK_SIZE 16
+#define CRYPT_BLOCK_MASK (CRYPT_BLOCK_SIZE-1) // 0xf
-struct CryptKeyCacheItem
+#define CRYPT5_KDF_LG2_COUNT 15 // LOG2 of PDKDF2 iteration count.
+#define CRYPT5_KDF_LG2_COUNT_MAX 24 // LOG2 of maximum accepted iteration count.
+#define CRYPT_VERSION 0 // Supported encryption version.
+
+
+class CryptData
{
-#ifndef _SFX_RTL_
- CryptKeyCacheItem()
+ struct KDF5CacheItem
{
- *Password=0;
- }
+ SecPassword Pwd;
+ byte Salt[SIZE_SALT50];
+ byte Key[32];
+ uint Lg2Count; // Log2 of PBKDF2 repetition count.
+ byte PswCheckValue[SHA256_DIGEST_SIZE];
+ byte HashKeyValue[SHA256_DIGEST_SIZE];
- ~CryptKeyCacheItem()
+ KDF5CacheItem() {Clean();}
+ ~KDF5CacheItem() {Clean();}
+
+ void Clean()
+ {
+ cleandata(Salt,sizeof(Salt));
+ cleandata(Key,sizeof(Key));
+ cleandata(&Lg2Count,sizeof(Lg2Count));
+ cleandata(PswCheckValue,sizeof(PswCheckValue));
+ cleandata(HashKeyValue,sizeof(HashKeyValue));
+ }
+ };
+
+ struct KDF3CacheItem
{
- memset(AESKey,0,sizeof(AESKey));
- memset(AESInit,0,sizeof(AESInit));
- memset(Password,0,sizeof(Password));
- }
-#endif
- byte AESKey[16],AESInit[16];
- char Password[MAXPASSWORD];
- bool SaltPresent;
- byte Salt[SALT_SIZE];
- bool HandsOffHash;
-};
+ SecPassword Pwd;
+ byte Salt[SIZE_SALT30];
+ byte Key[16];
+ byte Init[16];
+ bool SaltPresent;
+
+ KDF3CacheItem() {Clean();}
+ ~KDF3CacheItem() {Clean();}
+
+ void Clean()
+ {
+ cleandata(Salt,sizeof(Salt));
+ cleandata(Key,sizeof(Key));
+ cleandata(Init,sizeof(Init));
+ cleandata(&SaltPresent,sizeof(SaltPresent));
+ }
+ };
+
-class CryptData
-{
private:
- void Encode13(byte *Data,uint Count);
- void Decode13(byte *Data,uint Count);
- void Crypt15(byte *Data,uint Count);
- void UpdKeys(byte *Buf);
- void Swap(byte *Ch1,byte *Ch2);
- void SetOldKeys(char *Password);
+ void SetKey13(const char *Password);
+ void Decrypt13(byte *Data,size_t Count);
- Rijndael rin;
+ void SetKey15(const char *Password);
+ void Crypt15(byte *Data,size_t Count);
+
+ void SetKey20(const char *Password);
+ void Swap20(byte *Ch1,byte *Ch2);
+ void UpdKeys20(byte *Buf);
+ void EncryptBlock20(byte *Buf);
+ void DecryptBlock20(byte *Buf);
+
+ void SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt);
+ void SetKey50(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt,const byte *InitV,uint Lg2Cnt,byte *HashKey,byte *PswCheck);
+
+ KDF3CacheItem KDF3Cache[4];
+ uint KDF3CachePos;
- byte SubstTable[256];
- uint Key[4];
- ushort OldKey[4];
- byte PN1,PN2,PN3;
+ KDF5CacheItem KDF5Cache[4];
+ uint KDF5CachePos;
- byte AESKey[16],AESInit[16];
+ CRYPT_METHOD Method;
- static CryptKeyCacheItem Cache[4];
- static int CachePos;
+ Rijndael rin;
+
+ uint CRCTab[256]; // For RAR 1.5 and RAR 2.0 encryption.
+
+ byte SubstTable20[256];
+ uint Key20[4];
+
+ byte Key13[3];
+ ushort Key15[4];
public:
- void SetCryptKeys(char *Password,byte *Salt,bool Encrypt,bool OldOnly,bool HandsOffHash);
+ CryptData();
+ bool SetCryptKeys(bool Encrypt,CRYPT_METHOD Method,SecPassword *Password,
+ const byte *Salt,const byte *InitV,uint Lg2Cnt,
+ byte *HashKey,byte *PswCheck);
void SetAV15Encryption();
void SetCmt13Encryption();
- void EncryptBlock20(byte *Buf);
- void DecryptBlock20(byte *Buf);
- void EncryptBlock(byte *Buf,int Size);
- void DecryptBlock(byte *Buf,int Size);
- void Crypt(byte *Data,uint Count,int Method);
- static void SetSalt(byte *Salt,int SaltSize);
+ void EncryptBlock(byte *Buf,size_t Size);
+ void DecryptBlock(byte *Buf,size_t Size);
+ static void SetSalt(byte *Salt,size_t SaltSize);
+};
+
+
+class CheckPassword
+{
+ public:
+ enum CONFIDENCE {CONFIDENCE_HIGH,CONFIDENCE_MEDIUM,CONFIDENCE_LOW};
+ virtual CONFIDENCE GetConfidence()=0;
+ virtual bool Check(SecPassword *Password)=0;
};
+class RarCheckPassword:public CheckPassword
+{
+ private:
+ CryptData *Crypt;
+ uint Lg2Count;
+ byte Salt[SIZE_SALT50];
+ byte InitV[SIZE_INITV];
+ byte PswCheck[SIZE_PSWCHECK];
+ public:
+ RarCheckPassword()
+ {
+ Crypt=NULL;
+ }
+ ~RarCheckPassword()
+ {
+ delete Crypt;
+ }
+ void Set(byte *Salt,byte *InitV,uint Lg2Count,byte *PswCheck)
+ {
+ if (Crypt==NULL)
+ Crypt=new CryptData;
+ memcpy(this->Salt,Salt,sizeof(this->Salt));
+ memcpy(this->InitV,InitV,sizeof(this->InitV));
+ this->Lg2Count=Lg2Count;
+ memcpy(this->PswCheck,PswCheck,sizeof(this->PswCheck));
+ }
+ bool IsSet() {return Crypt!=NULL;}
+
+ // RAR5 provides the higly reliable 64 bit password verification value.
+ CONFIDENCE GetConfidence() {return CONFIDENCE_HIGH;}
+
+ bool Check(SecPassword *Password)
+ {
+ byte PswCheck[SIZE_PSWCHECK];
+ Crypt->SetCryptKeys(false,CRYPT_RAR50,Password,Salt,InitV,Lg2Count,NULL,PswCheck);
+ return memcmp(PswCheck,this->PswCheck,sizeof(this->PswCheck))==0;
+ }
+};
+
+void GetRnd(byte *RndBuf,size_t BufSize);
+
+void hmac_sha256(const byte *Key,size_t KeyLength,const byte *Data,
+ size_t DataLength,byte *ResDigest);
+void pbkdf2(const byte *pass, size_t pass_len, const byte *salt,
+ size_t salt_len,byte *key, byte *Value1, byte *Value2,
+ uint rounds);
+
+void ConvertHashToMAC(HashValue *Value,byte *Key);
+
#endif