]> git.proxmox.com Git - efi-boot-shim.git/blame - PasswordCrypt.c
New upstream version 15.7
[efi-boot-shim.git] / PasswordCrypt.c
CommitLineData
031e5cce
SM
1// SPDX-License-Identifier: BSD-2-Clause-Patent
2
3#include "shim.h"
4
3a838b14
GCPL
5#include <Library/BaseCryptLib.h>
6#include <openssl/sha.h>
5a898351 7#include <openssl/md5.h>
f892ac66 8
908eacc2
GCPL
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 */
114dad49 11#define BLOWFISH_HASH_SIZE 31 /* 184/6+1 */
5a898351
GCPL
12
13UINT16 get_hash_size (const UINT16 method)
14{
15 switch (method) {
908eacc2
GCPL
16 case TRADITIONAL_DES:
17 return TRAD_DES_HASH_SIZE;
5a898351 18 case EXTEND_BSDI_DES:
908eacc2 19 return BSDI_DES_HASH_SIZE;
5a898351
GCPL
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:
114dad49 27 return BLOWFISH_HASH_SIZE;
5a898351
GCPL
28 }
29
30 return 0;
31}
32
be5c35e1
GCPL
33static const char md5_salt_prefix[] = "$1$";
34
35static 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
3a838b14
GCPL
96static 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);
47a9d2c9 142 for (cnt = 0; cnt < 16ul + alt_result[0]; ++cnt)
3a838b14
GCPL
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
5a898351
GCPL
183static 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);
47a9d2c9 230 for (cnt = 0; cnt < 16ul + alt_result[0]; ++cnt)
5a898351
GCPL
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
114dad49
GCPL
271#define BF_RESULT_SIZE (7 + 22 + 31 + 1)
272
273static 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
3a838b14
GCPL
286EFI_STATUS password_crypt (const char *password, UINT32 pw_length,
287 const PASSWORD_CRYPT *pw_crypt, UINT8 *hash)
288{
f892ac66 289 EFI_STATUS efi_status;
3a838b14
GCPL
290
291 if (!pw_crypt)
292 return EFI_INVALID_PARAMETER;
293
294 switch (pw_crypt->method) {
908eacc2 295 case TRADITIONAL_DES:
3a838b14 296 case EXTEND_BSDI_DES:
f892ac66 297 efi_status = EFI_UNSUPPORTED;
3a838b14 298 break;
be5c35e1 299 case MD5_BASED:
f892ac66
MTL
300 efi_status = md5_crypt (password, pw_length,
301 (char *)pw_crypt->salt,
302 pw_crypt->salt_size, hash);
be5c35e1 303 break;
3a838b14 304 case SHA256_BASED:
f892ac66
MTL
305 efi_status = sha256_crypt(password, pw_length,
306 (char *)pw_crypt->salt,
307 pw_crypt->salt_size,
308 pw_crypt->iter_count, hash);
3a838b14
GCPL
309 break;
310 case SHA512_BASED:
f892ac66
MTL
311 efi_status = sha512_crypt(password, pw_length,
312 (char *)pw_crypt->salt,
313 pw_crypt->salt_size,
314 pw_crypt->iter_count, hash);
5a898351 315 break;
3a838b14 316 case BLOWFISH_BASED:
114dad49 317 if (pw_crypt->salt_size != (7 + 22 + 1)) {
f892ac66 318 efi_status = EFI_INVALID_PARAMETER;
114dad49
GCPL
319 break;
320 }
f892ac66
MTL
321 efi_status = blowfish_crypt(password, (char *)pw_crypt->salt,
322 hash);
3a838b14
GCPL
323 break;
324 default:
325 return EFI_INVALID_PARAMETER;
326 }
327
f892ac66 328 return efi_status;
3a838b14 329}