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