]> git.proxmox.com Git - efi-boot-shim.git/blob - PasswordCrypt.c
MokManager: support blowfish-based crypt() hash
[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 "PasswordCrypt.h"
7 #include "crypt_blowfish.h"
8
9 #define BLOWFISH_HASH_SIZE 31 /* 184/6+1 */
10
11 UINT16 get_hash_size (const UINT16 method)
12 {
13 switch (method) {
14 case TRANDITIONAL_DES:
15 return 64 / 8; /* per "man crypt" */
16 case EXTEND_BSDI_DES:
17 return 64 / 8; /* per "man crypt" */
18 case MD5_BASED:
19 return MD5_DIGEST_LENGTH;
20 case SHA256_BASED:
21 return SHA256_DIGEST_LENGTH;
22 case SHA512_BASED:
23 return SHA512_DIGEST_LENGTH;
24 case BLOWFISH_BASED:
25 return BLOWFISH_HASH_SIZE;
26 }
27
28 return 0;
29 }
30
31 static EFI_STATUS sha256_crypt (const char *key, UINT32 key_len,
32 const char *salt, UINT32 salt_size,
33 const UINT32 rounds, UINT8 *hash)
34 {
35 SHA256_CTX ctx, alt_ctx;
36 UINT8 alt_result[SHA256_DIGEST_SIZE];
37 UINT8 tmp_result[SHA256_DIGEST_SIZE];
38 UINT8 *cp, *p_bytes, *s_bytes;
39 UINTN cnt;
40
41 SHA256_Init(&ctx);
42 SHA256_Update(&ctx, key, key_len);
43 SHA256_Update(&ctx, salt, salt_size);
44
45 SHA256_Init(&alt_ctx);
46 SHA256_Update(&alt_ctx, key, key_len);
47 SHA256_Update(&alt_ctx, salt, salt_size);
48 SHA256_Update(&alt_ctx, key, key_len);
49 SHA256_Final(alt_result, &alt_ctx);
50
51 for (cnt = key_len; cnt > 32; cnt -= 32)
52 SHA256_Update(&ctx, alt_result, 32);
53 SHA256_Update(&ctx, alt_result, cnt);
54
55 for (cnt = key_len; cnt > 0; cnt >>= 1) {
56 if ((cnt & 1) != 0) {
57 SHA256_Update(&ctx, alt_result, 32);
58 } else {
59 SHA256_Update(&ctx, key, key_len);
60 }
61 }
62 SHA256_Final(alt_result, &ctx);
63
64 SHA256_Init(&alt_ctx);
65 for (cnt = 0; cnt < key_len; ++cnt)
66 SHA256_Update(&alt_ctx, key, key_len);
67 SHA256_Final(tmp_result, &alt_ctx);
68
69 cp = p_bytes = AllocatePool(key_len);
70 for (cnt = key_len; cnt >= 32; cnt -= 32) {
71 CopyMem(cp, tmp_result, 32);
72 cp += 32;
73 }
74 CopyMem(cp, tmp_result, cnt);
75
76 SHA256_Init(&alt_ctx);
77 for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt)
78 SHA256_Update(&alt_ctx, salt, salt_size);
79 SHA256_Final(tmp_result, &alt_ctx);
80
81 cp = s_bytes = AllocatePool(salt_size);
82 for (cnt = salt_size; cnt >= 32; cnt -= 32) {
83 CopyMem(cp, tmp_result, 32);
84 cp += 32;
85 }
86 CopyMem(cp, tmp_result, cnt);
87
88 for (cnt = 0; cnt < rounds; ++cnt) {
89 SHA256_Init(&ctx);
90
91 if ((cnt & 1) != 0)
92 SHA256_Update(&ctx, p_bytes, key_len);
93 else
94 SHA256_Update(&ctx, alt_result, 32);
95
96 if (cnt % 3 != 0)
97 SHA256_Update(&ctx, s_bytes, salt_size);
98
99 if (cnt % 7 != 0)
100 SHA256_Update(&ctx, p_bytes, key_len);
101
102 if ((cnt & 1) != 0)
103 SHA256_Update(&ctx, alt_result, 32);
104 else
105 SHA256_Update(&ctx, p_bytes, key_len);
106
107 SHA256_Final(alt_result, &ctx);
108 }
109
110 CopyMem(hash, alt_result, SHA256_DIGEST_SIZE);
111
112 FreePool(p_bytes);
113 FreePool(s_bytes);
114
115 return EFI_SUCCESS;
116 }
117
118 static EFI_STATUS sha512_crypt (const char *key, UINT32 key_len,
119 const char *salt, UINT32 salt_size,
120 const UINT32 rounds, UINT8 *hash)
121 {
122 SHA512_CTX ctx, alt_ctx;
123 UINT8 alt_result[SHA512_DIGEST_LENGTH];
124 UINT8 tmp_result[SHA512_DIGEST_LENGTH];
125 UINT8 *cp, *p_bytes, *s_bytes;
126 UINTN cnt;
127
128 SHA512_Init(&ctx);
129 SHA512_Update(&ctx, key, key_len);
130 SHA512_Update(&ctx, salt, salt_size);
131
132 SHA512_Init(&alt_ctx);
133 SHA512_Update(&alt_ctx, key, key_len);
134 SHA512_Update(&alt_ctx, salt, salt_size);
135 SHA512_Update(&alt_ctx, key, key_len);
136
137 SHA512_Final(alt_result, &alt_ctx);
138
139 for (cnt = key_len; cnt > 64; cnt -= 64)
140 SHA512_Update(&ctx, alt_result, 64);
141 SHA512_Update(&ctx, alt_result, cnt);
142
143 for (cnt = key_len; cnt > 0; cnt >>= 1) {
144 if ((cnt & 1) != 0) {
145 SHA512_Update(&ctx, alt_result, 64);
146 } else {
147 SHA512_Update(&ctx, key, key_len);
148 }
149 }
150 SHA512_Final(alt_result, &ctx);
151
152 SHA512_Init(&alt_ctx);
153 for (cnt = 0; cnt < key_len; ++cnt)
154 SHA512_Update(&alt_ctx, key, key_len);
155 SHA512_Final(tmp_result, &alt_ctx);
156
157 cp = p_bytes = AllocatePool(key_len);
158 for (cnt = key_len; cnt >= 64; cnt -= 64) {
159 CopyMem(cp, tmp_result, 64);
160 cp += 64;
161 }
162 CopyMem(cp, tmp_result, cnt);
163
164 SHA512_Init(&alt_ctx);
165 for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt)
166 SHA512_Update(&alt_ctx, salt, salt_size);
167 SHA512_Final(tmp_result, &alt_ctx);
168
169 cp = s_bytes = AllocatePool(salt_size);
170 for (cnt = salt_size; cnt >= 64; cnt -= 64) {
171 CopyMem(cp, tmp_result, 64);
172 cp += 64;
173 }
174 CopyMem(cp, tmp_result, cnt);
175
176 for (cnt = 0; cnt < rounds; ++cnt) {
177 SHA512_Init(&ctx);
178
179 if ((cnt & 1) != 0)
180 SHA512_Update(&ctx, p_bytes, key_len);
181 else
182 SHA512_Update(&ctx, alt_result, 64);
183
184 if (cnt % 3 != 0)
185 SHA512_Update(&ctx, s_bytes, salt_size);
186
187 if (cnt % 7 != 0)
188 SHA512_Update(&ctx, p_bytes, key_len);
189
190 if ((cnt & 1) != 0)
191 SHA512_Update(&ctx, alt_result, 64);
192 else
193 SHA512_Update(&ctx, p_bytes, key_len);
194
195 SHA512_Final(alt_result, &ctx);
196 }
197
198 CopyMem(hash, alt_result, SHA512_DIGEST_LENGTH);
199
200 FreePool(p_bytes);
201 FreePool(s_bytes);
202
203 return EFI_SUCCESS;
204 }
205
206 #define BF_RESULT_SIZE (7 + 22 + 31 + 1)
207
208 static EFI_STATUS blowfish_crypt (const char *key, const char *salt, UINT8 *hash)
209 {
210 char *retval, result[BF_RESULT_SIZE];
211
212 retval = crypt_blowfish_rn (key, salt, result, BF_RESULT_SIZE);
213 if (!retval)
214 return EFI_UNSUPPORTED;
215
216 CopyMem(hash, result + 7 + 22, BF_RESULT_SIZE);
217
218 return EFI_SUCCESS;
219 }
220
221 EFI_STATUS password_crypt (const char *password, UINT32 pw_length,
222 const PASSWORD_CRYPT *pw_crypt, UINT8 *hash)
223 {
224 EFI_STATUS status;
225
226 if (!pw_crypt)
227 return EFI_INVALID_PARAMETER;
228
229 switch (pw_crypt->method) {
230 case TRANDITIONAL_DES:
231 case EXTEND_BSDI_DES:
232 case MD5_BASED:
233 /* TODO unsupported */
234 status = EFI_UNSUPPORTED;
235 break;
236 case SHA256_BASED:
237 status = sha256_crypt(password, pw_length, (char *)pw_crypt->salt,
238 pw_crypt->salt_size, pw_crypt->iter_count,
239 hash);
240 break;
241 case SHA512_BASED:
242 status = sha512_crypt(password, pw_length, (char *)pw_crypt->salt,
243 pw_crypt->salt_size, pw_crypt->iter_count,
244 hash);
245 break;
246 case BLOWFISH_BASED:
247 if (pw_crypt->salt_size != (7 + 22 + 1)) {
248 status = EFI_INVALID_PARAMETER;
249 break;
250 }
251 status = blowfish_crypt(password, (char *)pw_crypt->salt, hash);
252 break;
253 default:
254 return EFI_INVALID_PARAMETER;
255 }
256
257 return status;
258 }