unrarsrc  6.1.7
About: unrar extracts, views and tests the contents of archives created with the RAR archiver.
  Fossies Dox: unrarsrc-6.1.7.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

crypt5.cpp
Go to the documentation of this file.
1static 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.
85void 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).
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
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
131void 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
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
192void 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
214static void TestPBKDF2();
215struct TestKDF {TestKDF() {TestPBKDF2();exit(0);}} GlobalTestKDF;
216
217void 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
#define BLAKE2_DIGEST_SIZE
Definition: blake2s.hpp:5
uint KDF5CachePos
Definition: crypt.hpp:65
void SetKey50(bool Encrypt, SecPassword *Password, const wchar *PwdW, const byte *Salt, const byte *InitV, uint Lg2Cnt, byte *HashKey, byte *PswCheck)
Definition: crypt5.cpp:131
KDF5CacheItem KDF5Cache[4]
Definition: crypt.hpp:64
Rijndael rin
Definition: crypt.hpp:69
void Init(bool Encrypt, const byte *key, uint keyLen, const byte *initVector)
Definition: rijndael.cpp:91
void mprintf(const wchar *fmt,...)
Definition: consio.cpp:118
void ConvertHashToMAC(HashValue *Value, byte *Key)
Definition: crypt5.cpp:192
void pbkdf2(const byte *Pwd, size_t PwdLength, const byte *Salt, size_t SaltLength, byte *Key, byte *V1, byte *V2, uint Count)
Definition: crypt5.cpp:85
static void hmac_sha256(const byte *Key, size_t KeyLength, const byte *Data, size_t DataLength, byte *ResDigest, sha256_context *ICtxOpt, bool *SetIOpt, sha256_context *RCtxOpt, bool *SetROpt)
Definition: crypt5.cpp:1
#define SIZE_PSWCHECK
Definition: crypt.hpp:12
#define SIZE_SALT50
Definition: crypt.hpp:9
#define CRYPT5_KDF_LG2_COUNT_MAX
Definition: crypt.hpp:19
@ HASH_CRC32
Definition: hash.hpp:4
@ HASH_BLAKE2
Definition: hash.hpp:4
#define Min(x, y)
Definition: rardefs.hpp:4
#define MAXPASSWORD
Definition: rardefs.hpp:14
#define ASIZE(x)
Definition: rardefs.hpp:10
wchar_t wchar
Definition: rartypes.hpp:13
unsigned int uint
Definition: rartypes.hpp:8
void RawPut4(uint32 Field, void *Data)
Definition: rawint.hpp:46
static byte U1[256][4]
Definition: rijndael.cpp:37
static byte U2[256][4]
Definition: rijndael.cpp:37
void SecHideData(void *Data, size_t DataSize, bool Encode, bool CrossProcess)
void cleandata(void *data, size_t size)
Definition: secpassword.cpp:80
void sha256_process(sha256_context *ctx, const void *Data, size_t Size)
Definition: sha256.cpp:90
void sha256_done(sha256_context *ctx, byte *Digest)
Definition: sha256.cpp:114
static const uint32 K[64]
Definition: sha256.cpp:4
void sha256_init(sha256_context *ctx)
Definition: sha256.cpp:35
#define SHA256_DIGEST_SIZE
Definition: sha256.hpp:4
byte HashKeyValue[SHA256_DIGEST_SIZE]
Definition: crypt.hpp:32
byte PswCheckValue[SHA256_DIGEST_SIZE]
Definition: crypt.hpp:31
byte Digest[SHA256_DIGEST_SIZE]
Definition: hash.hpp:16
HASH_TYPE Type
Definition: hash.hpp:12
uint CRC32
Definition: hash.hpp:15
void WideToUtf(const wchar *Src, char *Dest, size_t DestSize)
Definition: unicode.cpp:255