]> git.proxmox.com Git - efi-boot-shim.git/blob - PasswordCrypt.c
Cryptlib: Update to the latest edk2 commit
[efi-boot-shim.git] / PasswordCrypt.c
1 #include <efi.h>
2 #include <efilib.h>
3 #include <Library/BaseCryptLib.h>
4 #include <openssl/sha.h>
5 #include <openssl/md5.h>
6 #include <openssl/des.h>
7 #include "PasswordCrypt.h"
8 #include "crypt_blowfish.h"
9
10 #define TRAD_DES_HASH_SIZE 13 /* (64/6+1) + (12/6) */
11 #define BSDI_DES_HASH_SIZE 20 /* (64/6+1) + (24/6) + 4 + 1 */
12 #define BLOWFISH_HASH_SIZE 31 /* 184/6+1 */
13
14 UINT16 get_hash_size (const UINT16 method)
15 {
16 switch (method) {
17 case TRADITIONAL_DES:
18 return TRAD_DES_HASH_SIZE;
19 case EXTEND_BSDI_DES:
20 return BSDI_DES_HASH_SIZE;
21 case MD5_BASED:
22 return MD5_DIGEST_LENGTH;
23 case SHA256_BASED:
24 return SHA256_DIGEST_LENGTH;
25 case SHA512_BASED:
26 return SHA512_DIGEST_LENGTH;
27 case BLOWFISH_BASED:
28 return BLOWFISH_HASH_SIZE;
29 }
30
31 return 0;
32 }
33
34 static EFI_STATUS trad_des_crypt (const char *key, const char *salt, UINT8 *hash)
35 {
36 char result[TRAD_DES_HASH_SIZE + 1];
37 char *ret;
38
39 ret = DES_fcrypt(key, salt, result);
40 if (ret) {
41 CopyMem(hash, result, TRAD_DES_HASH_SIZE);
42 return EFI_SUCCESS;
43 }
44
45 return EFI_UNSUPPORTED;
46 }
47
48 static const char md5_salt_prefix[] = "$1$";
49
50 static EFI_STATUS md5_crypt (const char *key, UINT32 key_len,
51 const char *salt, UINT32 salt_size,
52 UINT8 *hash)
53 {
54 MD5_CTX ctx, alt_ctx;
55 UINT8 alt_result[MD5_DIGEST_LENGTH];
56 UINTN cnt;
57
58 MD5_Init(&ctx);
59 MD5_Update(&ctx, key, key_len);
60 MD5_Update(&ctx, md5_salt_prefix, sizeof(md5_salt_prefix) - 1);
61 MD5_Update(&ctx, salt, salt_size);
62
63 MD5_Init(&alt_ctx);
64 MD5_Update(&alt_ctx, key, key_len);
65 MD5_Update(&alt_ctx, salt, salt_size);
66 MD5_Update(&alt_ctx, key, key_len);
67 MD5_Final(alt_result, &alt_ctx);
68
69 for (cnt = key_len; cnt > 16; cnt -= 16)
70 MD5_Update(&ctx, alt_result, 16);
71 MD5_Update(&ctx, alt_result, cnt);
72
73 *alt_result = '\0';
74
75 for (cnt = key_len; cnt > 0; cnt >>= 1) {
76 if ((cnt & 1) != 0) {
77 MD5_Update(&ctx, alt_result, 1);
78 } else {
79 MD5_Update(&ctx, key, 1);
80 }
81 }
82 MD5_Final(alt_result, &ctx);
83
84 for (cnt = 0; cnt < 1000; ++cnt) {
85 MD5_Init(&ctx);
86
87 if ((cnt & 1) != 0)
88 MD5_Update(&ctx, key, key_len);
89 else
90 MD5_Update(&ctx, alt_result, 16);
91
92 if (cnt % 3 != 0)
93 MD5_Update(&ctx, salt, salt_size);
94
95 if (cnt % 7 != 0)
96 MD5_Update(&ctx, key, key_len);
97
98 if ((cnt & 1) != 0)
99 MD5_Update(&ctx, alt_result, 16);
100 else
101 MD5_Update(&ctx, key, key_len);
102
103 MD5_Final(alt_result, &ctx);
104 }
105
106 CopyMem(hash, alt_result, MD5_DIGEST_LENGTH);
107
108 return EFI_SUCCESS;
109 }
110
111 static EFI_STATUS sha256_crypt (const char *key, UINT32 key_len,
112 const char *salt, UINT32 salt_size,
113 const UINT32 rounds, UINT8 *hash)
114 {
115 SHA256_CTX ctx, alt_ctx;
116 UINT8 alt_result[SHA256_DIGEST_SIZE];
117 UINT8 tmp_result[SHA256_DIGEST_SIZE];
118 UINT8 *cp, *p_bytes, *s_bytes;
119 UINTN cnt;
120
121 SHA256_Init(&ctx);
122 SHA256_Update(&ctx, key, key_len);
123 SHA256_Update(&ctx, salt, salt_size);
124
125 SHA256_Init(&alt_ctx);
126 SHA256_Update(&alt_ctx, key, key_len);
127 SHA256_Update(&alt_ctx, salt, salt_size);
128 SHA256_Update(&alt_ctx, key, key_len);
129 SHA256_Final(alt_result, &alt_ctx);
130
131 for (cnt = key_len; cnt > 32; cnt -= 32)
132 SHA256_Update(&ctx, alt_result, 32);
133 SHA256_Update(&ctx, alt_result, cnt);
134
135 for (cnt = key_len; cnt > 0; cnt >>= 1) {
136 if ((cnt & 1) != 0) {
137 SHA256_Update(&ctx, alt_result, 32);
138 } else {
139 SHA256_Update(&ctx, key, key_len);
140 }
141 }
142 SHA256_Final(alt_result, &ctx);
143
144 SHA256_Init(&alt_ctx);
145 for (cnt = 0; cnt < key_len; ++cnt)
146 SHA256_Update(&alt_ctx, key, key_len);
147 SHA256_Final(tmp_result, &alt_ctx);
148
149 cp = p_bytes = AllocatePool(key_len);
150 for (cnt = key_len; cnt >= 32; cnt -= 32) {
151 CopyMem(cp, tmp_result, 32);
152 cp += 32;
153 }
154 CopyMem(cp, tmp_result, cnt);
155
156 SHA256_Init(&alt_ctx);
157 for (cnt = 0; cnt < 16ul + alt_result[0]; ++cnt)
158 SHA256_Update(&alt_ctx, salt, salt_size);
159 SHA256_Final(tmp_result, &alt_ctx);
160
161 cp = s_bytes = AllocatePool(salt_size);
162 for (cnt = salt_size; cnt >= 32; cnt -= 32) {
163 CopyMem(cp, tmp_result, 32);
164 cp += 32;
165 }
166 CopyMem(cp, tmp_result, cnt);
167
168 for (cnt = 0; cnt < rounds; ++cnt) {
169 SHA256_Init(&ctx);
170
171 if ((cnt & 1) != 0)
172 SHA256_Update(&ctx, p_bytes, key_len);
173 else
174 SHA256_Update(&ctx, alt_result, 32);
175
176 if (cnt % 3 != 0)
177 SHA256_Update(&ctx, s_bytes, salt_size);
178
179 if (cnt % 7 != 0)
180 SHA256_Update(&ctx, p_bytes, key_len);
181
182 if ((cnt & 1) != 0)
183 SHA256_Update(&ctx, alt_result, 32);
184 else
185 SHA256_Update(&ctx, p_bytes, key_len);
186
187 SHA256_Final(alt_result, &ctx);
188 }
189
190 CopyMem(hash, alt_result, SHA256_DIGEST_SIZE);
191
192 FreePool(p_bytes);
193 FreePool(s_bytes);
194
195 return EFI_SUCCESS;
196 }
197
198 static EFI_STATUS sha512_crypt (const char *key, UINT32 key_len,
199 const char *salt, UINT32 salt_size,
200 const UINT32 rounds, UINT8 *hash)
201 {
202 SHA512_CTX ctx, alt_ctx;
203 UINT8 alt_result[SHA512_DIGEST_LENGTH];
204 UINT8 tmp_result[SHA512_DIGEST_LENGTH];
205 UINT8 *cp, *p_bytes, *s_bytes;
206 UINTN cnt;
207
208 SHA512_Init(&ctx);
209 SHA512_Update(&ctx, key, key_len);
210 SHA512_Update(&ctx, salt, salt_size);
211
212 SHA512_Init(&alt_ctx);
213 SHA512_Update(&alt_ctx, key, key_len);
214 SHA512_Update(&alt_ctx, salt, salt_size);
215 SHA512_Update(&alt_ctx, key, key_len);
216
217 SHA512_Final(alt_result, &alt_ctx);
218
219 for (cnt = key_len; cnt > 64; cnt -= 64)
220 SHA512_Update(&ctx, alt_result, 64);
221 SHA512_Update(&ctx, alt_result, cnt);
222
223 for (cnt = key_len; cnt > 0; cnt >>= 1) {
224 if ((cnt & 1) != 0) {
225 SHA512_Update(&ctx, alt_result, 64);
226 } else {
227 SHA512_Update(&ctx, key, key_len);
228 }
229 }
230 SHA512_Final(alt_result, &ctx);
231
232 SHA512_Init(&alt_ctx);
233 for (cnt = 0; cnt < key_len; ++cnt)
234 SHA512_Update(&alt_ctx, key, key_len);
235 SHA512_Final(tmp_result, &alt_ctx);
236
237 cp = p_bytes = AllocatePool(key_len);
238 for (cnt = key_len; cnt >= 64; cnt -= 64) {
239 CopyMem(cp, tmp_result, 64);
240 cp += 64;
241 }
242 CopyMem(cp, tmp_result, cnt);
243
244 SHA512_Init(&alt_ctx);
245 for (cnt = 0; cnt < 16ul + alt_result[0]; ++cnt)
246 SHA512_Update(&alt_ctx, salt, salt_size);
247 SHA512_Final(tmp_result, &alt_ctx);
248
249 cp = s_bytes = AllocatePool(salt_size);
250 for (cnt = salt_size; cnt >= 64; cnt -= 64) {
251 CopyMem(cp, tmp_result, 64);
252 cp += 64;
253 }
254 CopyMem(cp, tmp_result, cnt);
255
256 for (cnt = 0; cnt < rounds; ++cnt) {
257 SHA512_Init(&ctx);
258
259 if ((cnt & 1) != 0)
260 SHA512_Update(&ctx, p_bytes, key_len);
261 else
262 SHA512_Update(&ctx, alt_result, 64);
263
264 if (cnt % 3 != 0)
265 SHA512_Update(&ctx, s_bytes, salt_size);
266
267 if (cnt % 7 != 0)
268 SHA512_Update(&ctx, p_bytes, key_len);
269
270 if ((cnt & 1) != 0)
271 SHA512_Update(&ctx, alt_result, 64);
272 else
273 SHA512_Update(&ctx, p_bytes, key_len);
274
275 SHA512_Final(alt_result, &ctx);
276 }
277
278 CopyMem(hash, alt_result, SHA512_DIGEST_LENGTH);
279
280 FreePool(p_bytes);
281 FreePool(s_bytes);
282
283 return EFI_SUCCESS;
284 }
285
286 #define BF_RESULT_SIZE (7 + 22 + 31 + 1)
287
288 static EFI_STATUS blowfish_crypt (const char *key, const char *salt, UINT8 *hash)
289 {
290 char *retval, result[BF_RESULT_SIZE];
291
292 retval = crypt_blowfish_rn (key, salt, result, BF_RESULT_SIZE);
293 if (!retval)
294 return EFI_UNSUPPORTED;
295
296 CopyMem(hash, result + 7 + 22, BF_RESULT_SIZE);
297
298 return EFI_SUCCESS;
299 }
300
301 EFI_STATUS password_crypt (const char *password, UINT32 pw_length,
302 const PASSWORD_CRYPT *pw_crypt, UINT8 *hash)
303 {
304 EFI_STATUS status;
305
306 if (!pw_crypt)
307 return EFI_INVALID_PARAMETER;
308
309 switch (pw_crypt->method) {
310 case TRADITIONAL_DES:
311 status = trad_des_crypt (password, (char *)pw_crypt->salt, hash);
312 break;
313 case EXTEND_BSDI_DES:
314 status = EFI_UNSUPPORTED;
315 break;
316 case MD5_BASED:
317 status = md5_crypt (password, pw_length, (char *)pw_crypt->salt,
318 pw_crypt->salt_size, hash);
319 break;
320 case SHA256_BASED:
321 status = sha256_crypt(password, pw_length, (char *)pw_crypt->salt,
322 pw_crypt->salt_size, pw_crypt->iter_count,
323 hash);
324 break;
325 case SHA512_BASED:
326 status = sha512_crypt(password, pw_length, (char *)pw_crypt->salt,
327 pw_crypt->salt_size, pw_crypt->iter_count,
328 hash);
329 break;
330 case BLOWFISH_BASED:
331 if (pw_crypt->salt_size != (7 + 22 + 1)) {
332 status = EFI_INVALID_PARAMETER;
333 break;
334 }
335 status = blowfish_crypt(password, (char *)pw_crypt->salt, hash);
336 break;
337 default:
338 return EFI_INVALID_PARAMETER;
339 }
340
341 return status;
342 }