Line | Count | Source (jump to first uncovered line) |
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 | 0 | { |
6 | 0 | const size_t Sha256BlockSize=64; // As defined in RFC 4868. |
7 | |
|
8 | 0 | byte KeyHash[SHA256_DIGEST_SIZE]; |
9 | 0 | if (KeyLength > Sha256BlockSize) // Convert longer keys to key hash. |
10 | 0 | { |
11 | 0 | sha256_context KCtx; |
12 | 0 | sha256_init(&KCtx); |
13 | 0 | sha256_process(&KCtx, Key, KeyLength); |
14 | 0 | sha256_done(&KCtx, KeyHash); |
15 | |
|
16 | 0 | Key = KeyHash; |
17 | 0 | KeyLength = SHA256_DIGEST_SIZE; |
18 | 0 | } |
19 | |
|
20 | 0 | byte KeyBuf[Sha256BlockSize]; // Store the padded key here. |
21 | 0 | sha256_context ICtx; |
22 | |
|
23 | 0 | if (ICtxOpt!=NULL && *SetIOpt) |
24 | 0 | ICtx=*ICtxOpt; // Use already calculated the first block context. |
25 | 0 | else |
26 | 0 | { |
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 | 0 | for (size_t I = 0; I < KeyLength; I++) // Use 0x36 padding for inner digest. |
32 | 0 | KeyBuf[I] = Key[I] ^ 0x36; |
33 | 0 | for (size_t I = KeyLength; I < Sha256BlockSize; I++) |
34 | 0 | KeyBuf[I] = 0x36; |
35 | |
|
36 | 0 | sha256_init(&ICtx); |
37 | 0 | sha256_process(&ICtx, KeyBuf, Sha256BlockSize); // Hash padded key. |
38 | 0 | } |
39 | |
|
40 | 0 | if (ICtxOpt!=NULL && !*SetIOpt) // Store constant context for further reuse. |
41 | 0 | { |
42 | 0 | *ICtxOpt=ICtx; |
43 | 0 | *SetIOpt=true; |
44 | 0 | } |
45 | |
|
46 | 0 | sha256_process(&ICtx, Data, DataLength); // Hash data. |
47 | |
|
48 | 0 | byte IDig[SHA256_DIGEST_SIZE]; // Internal digest for padded key and data. |
49 | 0 | sha256_done(&ICtx, IDig); |
50 | |
|
51 | 0 | sha256_context RCtx; |
52 | |
|
53 | 0 | if (RCtxOpt!=NULL && *SetROpt) |
54 | 0 | RCtx=*RCtxOpt; // Use already calculated first block context. |
55 | 0 | else |
56 | 0 | { |
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 | 0 | for (size_t I = 0; I < KeyLength; I++) // Use 0x5c for outer key padding. |
62 | 0 | KeyBuf[I] = Key[I] ^ 0x5c; |
63 | 0 | for (size_t I = KeyLength; I < Sha256BlockSize; I++) |
64 | 0 | KeyBuf[I] = 0x5c; |
65 | |
|
66 | 0 | sha256_init(&RCtx); |
67 | 0 | sha256_process(&RCtx, KeyBuf, Sha256BlockSize); // Hash padded key. |
68 | 0 | } |
69 | |
|
70 | 0 | if (RCtxOpt!=NULL && !*SetROpt) // Store constant context for further reuse. |
71 | 0 | { |
72 | 0 | *RCtxOpt=RCtx; |
73 | 0 | *SetROpt=true; |
74 | 0 | } |
75 | |
|
76 | 0 | sha256_process(&RCtx, IDig, SHA256_DIGEST_SIZE); // Hash internal digest. |
77 | |
|
78 | 0 | sha256_done(&RCtx, ResDigest); |
79 | 0 | } |
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 | 0 | { |
89 | 0 | const size_t MaxSalt=64; |
90 | 0 | byte SaltData[MaxSalt+4]; |
91 | 0 | memcpy(SaltData, Salt, Min(SaltLength,MaxSalt)); |
92 | |
|
93 | 0 | SaltData[SaltLength + 0] = 0; // Block index appened to salt. |
94 | 0 | SaltData[SaltLength + 1] = 0; // |
95 | 0 | SaltData[SaltLength + 2] = 0; // Since we do not request the key width |
96 | 0 | SaltData[SaltLength + 3] = 1; // exceeding HMAC width, it is always 1. |
97 | | |
98 | | // First iteration: HMAC of password, salt and block index (1). |
99 | 0 | byte U1[SHA256_DIGEST_SIZE]; |
100 | 0 | hmac_sha256(Pwd, PwdLength, SaltData, SaltLength + 4, U1, NULL, NULL, NULL, NULL); |
101 | 0 | byte Fn[SHA256_DIGEST_SIZE]; // Current function value. |
102 | 0 | memcpy(Fn, U1, sizeof(Fn)); // Function at first iteration. |
103 | |
|
104 | 0 | uint CurCount[] = { Count-1, 16, 16 }; |
105 | 0 | byte *CurValue[] = { Key , V1, V2 }; |
106 | | |
107 | 0 | sha256_context ICtxOpt,RCtxOpt; |
108 | 0 | bool SetIOpt=false,SetROpt=false; |
109 | | |
110 | 0 | byte U2[SHA256_DIGEST_SIZE]; |
111 | 0 | for (uint I = 0; I < 3; I++) // For output key and 2 supplementary values. |
112 | 0 | { |
113 | 0 | for (uint J = 0; J < CurCount[I]; J++) |
114 | 0 | { |
115 | | // U2 = PRF (P, U1). |
116 | 0 | hmac_sha256(Pwd, PwdLength, U1, sizeof(U1), U2, &ICtxOpt, &SetIOpt, &RCtxOpt, &SetROpt); |
117 | 0 | memcpy(U1, U2, sizeof(U1)); |
118 | 0 | for (uint K = 0; K < sizeof(Fn); K++) // Function ^= U. |
119 | 0 | Fn[K] ^= U1[K]; |
120 | 0 | } |
121 | 0 | memcpy(CurValue[I], Fn, SHA256_DIGEST_SIZE); |
122 | 0 | } |
123 | |
|
124 | 0 | cleandata(SaltData, sizeof(SaltData)); |
125 | 0 | cleandata(Fn, sizeof(Fn)); |
126 | 0 | cleandata(U1, sizeof(U1)); |
127 | 0 | cleandata(U2, sizeof(U2)); |
128 | 0 | } |
129 | | |
130 | | |
131 | | bool CryptData::SetKey50(bool Encrypt,SecPassword *Password,const wchar *PwdW, |
132 | | const byte *Salt,const byte *InitV,uint Lg2Cnt,byte *HashKey, |
133 | | byte *PswCheck) |
134 | 0 | { |
135 | 0 | if (Lg2Cnt>CRYPT5_KDF_LG2_COUNT_MAX) |
136 | 0 | return false; |
137 | | |
138 | 0 | byte Key[32],PswCheckValue[SHA256_DIGEST_SIZE],HashKeyValue[SHA256_DIGEST_SIZE]; |
139 | 0 | bool Found=false; |
140 | 0 | for (uint I=0;I<ASIZE(KDF5Cache);I++) |
141 | 0 | { |
142 | 0 | KDF5CacheItem *Item=KDF5Cache+I; |
143 | 0 | if (Item->Pwd==*Password && Item->Lg2Count==Lg2Cnt && |
144 | 0 | memcmp(Item->Salt,Salt,SIZE_SALT50)==0) |
145 | 0 | { |
146 | 0 | memcpy(Key,Item->Key,sizeof(Key)); |
147 | 0 | SecHideData(Key,sizeof(Key),false,false); |
148 | |
|
149 | 0 | memcpy(PswCheckValue,Item->PswCheckValue,sizeof(PswCheckValue)); |
150 | 0 | memcpy(HashKeyValue,Item->HashKeyValue,sizeof(HashKeyValue)); |
151 | 0 | Found=true; |
152 | 0 | break; |
153 | 0 | } |
154 | 0 | } |
155 | |
|
156 | 0 | if (!Found) |
157 | 0 | { |
158 | 0 | char PwdUtf[MAXPASSWORD*4]; |
159 | 0 | WideToUtf(PwdW,PwdUtf,ASIZE(PwdUtf)); |
160 | | |
161 | 0 | pbkdf2((byte *)PwdUtf,strlen(PwdUtf),Salt,SIZE_SALT50,Key,HashKeyValue,PswCheckValue,(1<<Lg2Cnt)); |
162 | 0 | cleandata(PwdUtf,sizeof(PwdUtf)); |
163 | |
|
164 | 0 | KDF5CacheItem *Item=KDF5Cache+(KDF5CachePos++ % ASIZE(KDF5Cache)); |
165 | 0 | Item->Lg2Count=Lg2Cnt; |
166 | 0 | Item->Pwd=*Password; |
167 | 0 | memcpy(Item->Salt,Salt,SIZE_SALT50); |
168 | 0 | memcpy(Item->Key,Key,sizeof(Item->Key)); |
169 | 0 | memcpy(Item->PswCheckValue,PswCheckValue,sizeof(PswCheckValue)); |
170 | 0 | memcpy(Item->HashKeyValue,HashKeyValue,sizeof(HashKeyValue)); |
171 | 0 | SecHideData(Item->Key,sizeof(Item->Key),true,false); |
172 | 0 | } |
173 | 0 | if (HashKey!=NULL) |
174 | 0 | memcpy(HashKey,HashKeyValue,SHA256_DIGEST_SIZE); |
175 | 0 | if (PswCheck!=NULL) |
176 | 0 | { |
177 | 0 | memset(PswCheck,0,SIZE_PSWCHECK); |
178 | 0 | for (uint I=0;I<SHA256_DIGEST_SIZE;I++) |
179 | 0 | PswCheck[I%SIZE_PSWCHECK]^=PswCheckValue[I]; |
180 | 0 | cleandata(PswCheckValue,sizeof(PswCheckValue)); |
181 | 0 | } |
182 | | |
183 | | // NULL initialization vector is possible if we only need the password |
184 | | // check value for archive encryption header. |
185 | 0 | if (InitV!=NULL) |
186 | 0 | rin.Init(Encrypt, Key, 256, InitV); |
187 | |
|
188 | 0 | cleandata(Key,sizeof(Key)); |
189 | 0 | return true; |
190 | 0 | } |
191 | | |
192 | | |
193 | | void ConvertHashToMAC(HashValue *Value,byte *Key) |
194 | 0 | { |
195 | 0 | if (Value->Type==HASH_CRC32) |
196 | 0 | { |
197 | 0 | byte RawCRC[4]; |
198 | 0 | RawPut4(Value->CRC32,RawCRC); |
199 | 0 | byte Digest[SHA256_DIGEST_SIZE]; |
200 | 0 | hmac_sha256(Key,SHA256_DIGEST_SIZE,RawCRC,sizeof(RawCRC),Digest,NULL,NULL,NULL,NULL); |
201 | 0 | Value->CRC32=0; |
202 | 0 | for (uint I=0;I<ASIZE(Digest);I++) |
203 | 0 | Value->CRC32^=Digest[I] << ((I & 3) * 8); |
204 | 0 | Value->CRC32&=0xffffffff; // In case the variable size is larger than 32-bit. |
205 | 0 | } |
206 | 0 | if (Value->Type==HASH_BLAKE2) |
207 | 0 | { |
208 | 0 | byte Digest[BLAKE2_DIGEST_SIZE]; |
209 | 0 | hmac_sha256(Key,BLAKE2_DIGEST_SIZE,Value->Digest,sizeof(Value->Digest),Digest,NULL,NULL,NULL,NULL); |
210 | 0 | memcpy(Value->Digest,Digest,sizeof(Value->Digest)); |
211 | 0 | } |
212 | 0 | } |
213 | | |
214 | | |
215 | | #if 0 |
216 | | static void TestPBKDF2(); |
217 | | struct TestKDF {TestKDF() {TestPBKDF2();exit(0);}} GlobalTestKDF; |
218 | | |
219 | | void TestPBKDF2() // Test PBKDF2 HMAC-SHA256 |
220 | | { |
221 | | byte Key[32],V1[32],V2[32]; |
222 | | |
223 | | pbkdf2((byte *)"password", 8, (byte *)"salt", 4, Key, V1, V2, 1); |
224 | | 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 }; |
225 | | mprintf(L"\nPBKDF2 test1: %s", memcmp(Key,Res1,32)==0 ? L"OK":L"Failed"); |
226 | | |
227 | | pbkdf2((byte *)"password", 8, (byte *)"salt", 4, Key, V1, V2, 4096); |
228 | | 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 }; |
229 | | mprintf(L"\nPBKDF2 test2: %s", memcmp(Key,Res2,32)==0 ? L"OK":L"Failed"); |
230 | | |
231 | | 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); |
232 | | 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}; |
233 | | mprintf(L"\nPBKDF2 test3: %s", memcmp(Key,Res3,32)==0 ? L"OK":L"Failed"); |
234 | | } |
235 | | #endif |