]>
Commit | Line | Data |
---|---|---|
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 | |
13 | UINT16 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 |
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 | ||
3a838b14 GCPL |
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); | |
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 |
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); | |
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 | ||
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 | ||
3a838b14 GCPL |
286 | EFI_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 | } |