1 #include "crypt-port.h"
2
3 #include <errno.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6
7 static const char *const entropy[] =
8 {
9 "\x58\x35\xcd\x26\x03\xab\x2c\x14\x92\x13\x1e\x59\xb0\xbc\xfe\xd5",
10 "\x9b\x35\xa2\x45\xeb\x68\x9e\x8f\xd9\xa9\x09\x71\xcc\x4d\x21\x44",
11 "\x25\x13\xc5\x94\xc3\x93\x1d\xf4\xfd\xd4\x4f\xbd\x10\xe5\x28\x08",
12 "\xa0\x2d\x35\x70\xa8\x0b\xc3\xad\xdf\x61\x69\xb3\x19\xda\x7e\x8d",
13 0
14 };
15
16 #if INCLUDE_descrypt
17 static const char *const des_expected_output[] = { "Mp", "Pp", "ZH", "Uh"};
18 #endif
19 #if INCLUDE_bigcrypt && !INCLUDE_descrypt
20 static const char *const big_expected_output[] =
21 {
22 "Mp............",
23 "Pp............",
24 "ZH............",
25 "Uh............"
26 };
27 #endif
28 #if INCLUDE_bsdicrypt
29 static const char *const bsdi_expected_output[] =
30 {
31 "_J9..MJHn",
32 "_J9..PKXc",
33 "_J9..ZAFl",
34 "_J9..UqGB"
35 };
36 static const char *const bsdi_expected_output_r[] =
37 {
38 "_/.2.MJHn",
39 "_/.2.PKXc",
40 "_/.2.ZAFl",
41 "_/.2.UqGB"
42 };
43 static const char *const bsdi_expected_output_l[] =
44 {
45 "_/...MJHn",
46 "_/...PKXc",
47 "_/...ZAFl",
48 "_/...UqGB"
49 };
50 static const char *const bsdi_expected_output_h[] =
51 {
52 "_zzzzMJHn",
53 "_zzzzPKXc",
54 "_zzzzZAFl",
55 "_zzzzUqGB"
56 };
57 #endif
58 #if INCLUDE_md5crypt
59 static const char *const md5_expected_output[] =
60 {
61 "$1$MJHnaAke",
62 "$1$PKXc3hCO",
63 "$1$ZAFlICwY",
64 "$1$UqGBkVu0"
65 };
66 #endif
67 #if INCLUDE_sunmd5
68 static const char *const sunmd5_expected_output[] =
69 {
70 "$md5,rounds=55349$BPm.fm03$",
71 "$md5,rounds=72501$WKoucttX$",
72 "$md5,rounds=42259$3HtkHq/x$",
73 "$md5,rounds=73773$p.5e9AQf$",
74 };
75 static const char *const sunmd5_expected_output_l[] =
76 {
77 "$md5,rounds=55349$BPm.fm03$",
78 "$md5,rounds=72501$WKoucttX$",
79 "$md5,rounds=42259$3HtkHq/x$",
80 "$md5,rounds=73773$p.5e9AQf$",
81 };
82 static const char *const sunmd5_expected_output_h[] =
83 {
84 "$md5,rounds=4294924340$BPm.fm03$",
85 "$md5,rounds=4294941492$WKoucttX$",
86 "$md5,rounds=4294911250$3HtkHq/x$",
87 "$md5,rounds=4294942764$p.5e9AQf$",
88 };
89 #endif
90 #if INCLUDE_sha1crypt
91 static const char *const sha1_expected_output[] =
92 {
93 "$sha1$248488$ggu.H673kaZ5$",
94 "$sha1$248421$SWqudaxXA5L0$",
95 "$sha1$257243$RAtkIrDxEovH$",
96 "$sha1$250464$1j.eVxRfNAPO$",
97 };
98 static const char *const sha1_expected_output_l[] =
99 {
100 "$sha1$4$ggu.H673kaZ5$",
101 "$sha1$4$SWqudaxXA5L0$",
102 "$sha1$4$RAtkIrDxEovH$",
103 "$sha1$4$1j.eVxRfNAPO$",
104 };
105 static const char *const sha1_expected_output_h[] =
106 {
107 "$sha1$3643984551$ggu.H673kaZ5$",
108 "$sha1$4200450659$SWqudaxXA5L0$",
109 "$sha1$3946507480$RAtkIrDxEovH$",
110 "$sha1$3486175838$1j.eVxRfNAPO$",
111 };
112 #endif
113 #if INCLUDE_sha256crypt
114 static const char *const sha256_expected_output[] =
115 {
116 "$5$MJHnaAkegEVYHsFK",
117 "$5$PKXc3hCOSyMqdaEQ",
118 "$5$ZAFlICwYRETzIzIj",
119 "$5$UqGBkVu01rurVZqg"
120 };
121 static const char *const sha256_expected_output_r[] =
122 {
123 "$5$rounds=10191$MJHnaAkegEVYHsFK",
124 "$5$rounds=10191$PKXc3hCOSyMqdaEQ",
125 "$5$rounds=10191$ZAFlICwYRETzIzIj",
126 "$5$rounds=10191$UqGBkVu01rurVZqg"
127 };
128 static const char *const sha256_expected_output_l[] =
129 {
130 "$5$rounds=1000$MJHnaAkegEVYHsFK",
131 "$5$rounds=1000$PKXc3hCOSyMqdaEQ",
132 "$5$rounds=1000$ZAFlICwYRETzIzIj",
133 "$5$rounds=1000$UqGBkVu01rurVZqg"
134 };
135 static const char *const sha256_expected_output_h[] =
136 {
137 "$5$rounds=999999999$MJHnaAkegEVYHsFK",
138 "$5$rounds=999999999$PKXc3hCOSyMqdaEQ",
139 "$5$rounds=999999999$ZAFlICwYRETzIzIj",
140 "$5$rounds=999999999$UqGBkVu01rurVZqg"
141 };
142 #endif
143 #if INCLUDE_sha512crypt
144 static const char *const sha512_expected_output[] =
145 {
146 "$6$MJHnaAkegEVYHsFK",
147 "$6$PKXc3hCOSyMqdaEQ",
148 "$6$ZAFlICwYRETzIzIj",
149 "$6$UqGBkVu01rurVZqg"
150 };
151 static const char *const sha512_expected_output_r[] =
152 {
153 "$6$rounds=10191$MJHnaAkegEVYHsFK",
154 "$6$rounds=10191$PKXc3hCOSyMqdaEQ",
155 "$6$rounds=10191$ZAFlICwYRETzIzIj",
156 "$6$rounds=10191$UqGBkVu01rurVZqg"
157 };
158 static const char *const sha512_expected_output_l[] =
159 {
160 "$6$rounds=1000$MJHnaAkegEVYHsFK",
161 "$6$rounds=1000$PKXc3hCOSyMqdaEQ",
162 "$6$rounds=1000$ZAFlICwYRETzIzIj",
163 "$6$rounds=1000$UqGBkVu01rurVZqg"
164 };
165 static const char *const sha512_expected_output_h[] =
166 {
167 "$6$rounds=999999999$MJHnaAkegEVYHsFK",
168 "$6$rounds=999999999$PKXc3hCOSyMqdaEQ",
169 "$6$rounds=999999999$ZAFlICwYRETzIzIj",
170 "$6$rounds=999999999$UqGBkVu01rurVZqg"
171 };
172 #endif
173 #if INCLUDE_bcrypt
174 static const char *const bcrypt_b_expected_output[] =
175 {
176 "$2b$05$UBVLHeMpJ/QQCv3XqJx8zO",
177 "$2b$05$kxUgPcrmlm9XoOjvxCyfP.",
178 "$2b$05$HPNDjKMRFdR7zC87CMSmA.",
179 "$2b$05$mAyzaIeJu41dWUkxEbn8hO"
180 };
181 static const char *const bcrypt_b_expected_output_l[] =
182 {
183 "$2b$04$UBVLHeMpJ/QQCv3XqJx8zO",
184 "$2b$04$kxUgPcrmlm9XoOjvxCyfP.",
185 "$2b$04$HPNDjKMRFdR7zC87CMSmA.",
186 "$2b$04$mAyzaIeJu41dWUkxEbn8hO"
187 };
188 static const char *const bcrypt_b_expected_output_h[] =
189 {
190 "$2b$31$UBVLHeMpJ/QQCv3XqJx8zO",
191 "$2b$31$kxUgPcrmlm9XoOjvxCyfP.",
192 "$2b$31$HPNDjKMRFdR7zC87CMSmA.",
193 "$2b$31$mAyzaIeJu41dWUkxEbn8hO"
194 };
195 #endif
196 #if INCLUDE_bcrypt_a
197 static const char *const bcrypt_a_expected_output[] =
198 {
199 "$2a$05$UBVLHeMpJ/QQCv3XqJx8zO",
200 "$2a$05$kxUgPcrmlm9XoOjvxCyfP.",
201 "$2a$05$HPNDjKMRFdR7zC87CMSmA.",
202 "$2a$05$mAyzaIeJu41dWUkxEbn8hO"
203 };
204 #endif
205 #if INCLUDE_bcrypt_y
206 static const char *const bcrypt_y_expected_output[] =
207 {
208 "$2y$05$UBVLHeMpJ/QQCv3XqJx8zO",
209 "$2y$05$kxUgPcrmlm9XoOjvxCyfP.",
210 "$2y$05$HPNDjKMRFdR7zC87CMSmA.",
211 "$2y$05$mAyzaIeJu41dWUkxEbn8hO"
212 };
213 #endif
214 #if INCLUDE_yescrypt
215 static const char *yescrypt_expected_output[] =
216 {
217 "$y$j9T$MJHnaAkegEVYHsFKkmfzJ1",
218 "$y$j9T$PKXc3hCOSyMqdaEQArI62/",
219 "$y$j9T$ZAFlICwYRETzIzIjEIC86.",
220 "$y$j9T$UqGBkVu01rurVZqgNchTB0"
221 };
222 static const char *yescrypt_expected_output_l[] =
223 {
224 "$y$j75$MJHnaAkegEVYHsFKkmfzJ1",
225 "$y$j75$PKXc3hCOSyMqdaEQArI62/",
226 "$y$j75$ZAFlICwYRETzIzIjEIC86.",
227 "$y$j75$UqGBkVu01rurVZqgNchTB0"
228 };
229 static const char *yescrypt_expected_output_h[] =
230 {
231 "$y$jFT$MJHnaAkegEVYHsFKkmfzJ1",
232 "$y$jFT$PKXc3hCOSyMqdaEQArI62/",
233 "$y$jFT$ZAFlICwYRETzIzIjEIC86.",
234 "$y$jFT$UqGBkVu01rurVZqgNchTB0"
235 };
236 #endif
237 #if INCLUDE_scrypt
238 static const char *scrypt_expected_output[] =
239 {
240 "$7$CU..../....MJHnaAkegEVYHsFKkmfzJ1",
241 "$7$CU..../....PKXc3hCOSyMqdaEQArI62/",
242 "$7$CU..../....ZAFlICwYRETzIzIjEIC86.",
243 "$7$CU..../....UqGBkVu01rurVZqgNchTB0"
244 };
245 static const char *scrypt_expected_output_l[] =
246 {
247 "$7$BU..../....MJHnaAkegEVYHsFKkmfzJ1",
248 "$7$BU..../....PKXc3hCOSyMqdaEQArI62/",
249 "$7$BU..../....ZAFlICwYRETzIzIjEIC86.",
250 "$7$BU..../....UqGBkVu01rurVZqgNchTB0"
251 };
252 static const char *scrypt_expected_output_h[] =
253 {
254 "$7$GU..../....MJHnaAkegEVYHsFKkmfzJ1",
255 "$7$GU..../....PKXc3hCOSyMqdaEQArI62/",
256 "$7$GU..../....ZAFlICwYRETzIzIjEIC86.",
257 "$7$GU..../....UqGBkVu01rurVZqgNchTB0"
258 };
259 #endif
260 #if INCLUDE_gost_yescrypt
261 static const char *gost_yescrypt_expected_output[] =
262 {
263 "$gy$j9T$MJHnaAkegEVYHsFKkmfzJ1",
264 "$gy$j9T$PKXc3hCOSyMqdaEQArI62/",
265 "$gy$j9T$ZAFlICwYRETzIzIjEIC86.",
266 "$gy$j9T$UqGBkVu01rurVZqgNchTB0"
267 };
268 static const char *gost_yescrypt_expected_output_l[] =
269 {
270 "$gy$j75$MJHnaAkegEVYHsFKkmfzJ1",
271 "$gy$j75$PKXc3hCOSyMqdaEQArI62/",
272 "$gy$j75$ZAFlICwYRETzIzIjEIC86.",
273 "$gy$j75$UqGBkVu01rurVZqgNchTB0"
274 };
275 static const char *gost_yescrypt_expected_output_h[] =
276 {
277 "$gy$jFT$MJHnaAkegEVYHsFKkmfzJ1",
278 "$gy$jFT$PKXc3hCOSyMqdaEQArI62/",
279 "$gy$jFT$ZAFlICwYRETzIzIjEIC86.",
280 "$gy$jFT$UqGBkVu01rurVZqgNchTB0"
281 };
282 #endif
283
284 struct testcase
285 {
286 const char *prefix;
287 const char *const *expected_output;
288 unsigned int expected_len;
289 unsigned int expected_auto_len;
290 unsigned long rounds;
291 };
292
293 // For all hashing methods with a linear cost parameter (that is,
294 // DES/BSD, MD5/Sun, SHA1, SHA256, and SHA512), crypt_gensalt will
295 // accept any value in the range of 'unsigned long' and clip it to the
296 // actual valid range.
297 #define MIN_LINEAR_COST 1
298 #define MAX_LINEAR_COST ULONG_MAX
299
300 static const struct testcase testcases[] =
301 {
302 #if INCLUDE_descrypt
303 { "", des_expected_output, 2, 0, 0 },
304 // DES doesn't have variable round count.
305 #endif
306 #if INCLUDE_bigcrypt && !INCLUDE_descrypt
307 { "", big_expected_output, 14, 0, 0 },
308 // bigcrypt doesn't have variable round count.
309 #endif
310 #if INCLUDE_bsdicrypt
311 { "_", bsdi_expected_output, 9, 0, 0 },
312 // BSDI/DES always emits a round count.
313 // The _r expectation is used to verify that even inputs are
314 // made odd, rather than rejected.
315 { "_", bsdi_expected_output_r, 9, 0, 16384 },
316 { "_", bsdi_expected_output_l, 9, 0, MIN_LINEAR_COST },
317 { "_", bsdi_expected_output_h, 9, 0, MAX_LINEAR_COST },
318 #endif
319 #if INCLUDE_md5crypt
320 { "$1$", md5_expected_output, 11, 0, 0 },
321 // MD5/BSD doesn't have variable round count.
322 #endif
323 #if INCLUDE_sunmd5
324 { "$md5", sunmd5_expected_output, 27, 0, 0 },
325 // MD5/Sun always emits a round count.
326 { "$md5", sunmd5_expected_output_l, 27, 0, MIN_LINEAR_COST },
327 { "$md5", sunmd5_expected_output_h, 32, 0, MAX_LINEAR_COST },
328 #endif
329 #if INCLUDE_sha1crypt
330 { "$sha1", sha1_expected_output, 26, 34, 0 },
331 // SHA1/PBKDF always emits a round count.
332 { "$sha1", sha1_expected_output_l, 21, 29, MIN_LINEAR_COST },
333 { "$sha1", sha1_expected_output_h, 30, 38, MAX_LINEAR_COST },
334 #endif
335 #if INCLUDE_sha256crypt
336 { "$5$", sha256_expected_output, 19, 0, 0 },
337 { "$5$", sha256_expected_output_r, 32, 0, 10191 },
338 { "$5$", sha256_expected_output_l, 31, 0, MIN_LINEAR_COST },
339 { "$5$", sha256_expected_output_h, 36, 0, MAX_LINEAR_COST },
340 #endif
341 #if INCLUDE_sha512crypt
342 { "$6$", sha512_expected_output, 19, 0, 0 },
343 { "$6$", sha512_expected_output_r, 32, 0, 10191 },
344 { "$6$", sha512_expected_output_l, 31, 0, MIN_LINEAR_COST },
345 { "$6$", sha512_expected_output_h, 36, 0, MAX_LINEAR_COST },
346 #endif
347 #if INCLUDE_bcrypt
348 { "$2b$", bcrypt_b_expected_output, 29, 0, 0 },
349 // bcrypt always emits a cost parameter.
350 // bcrypt's cost parameter is exponential, not linear, and
351 // values outside the documented range are errors.
352 { "$2b$", bcrypt_b_expected_output_l, 29, 0, 4 },
353 { "$2b$", bcrypt_b_expected_output_h, 29, 0, 31 },
354 #endif
355 // Salt generation for legacy bcrypt variants uses the same code as
356 // the 'b' variant, so we don't bother testing them on non-default
357 // rounds.
358 #if INCLUDE_bcrypt_a
359 { "$2a$", bcrypt_a_expected_output, 29, 0, 0 },
360 #endif
361 #if INCLUDE_bcrypt_y
362 { "$2y$", bcrypt_y_expected_output, 29, 0, 0 },
363 #endif
364 #if INCLUDE_yescrypt
365 { "$y$", yescrypt_expected_output, 29, 29, 0 },
366 { "$y$", yescrypt_expected_output_l, 29, 29, 1 },
367 { "$y$", yescrypt_expected_output_h, 29, 29, 11 },
368 #endif
369 #if INCLUDE_scrypt
370 { "$7$", scrypt_expected_output, 36, 36, 0 },
371 { "$7$", scrypt_expected_output_l, 36, 36, 6 },
372 { "$7$", scrypt_expected_output_h, 36, 36, 11 },
373 #endif
374 #if INCLUDE_gost_yescrypt
375 { "$gy$", gost_yescrypt_expected_output, 30, 30, 0 },
376 { "$gy$", gost_yescrypt_expected_output_l, 30, 30, 1 },
377 { "$gy$", gost_yescrypt_expected_output_h, 30, 30, 11 },
378 #endif
379 { 0, 0, 0, 0, 0 }
380 };
381
382 /* The "best available" hashing method. */
383 #if INCLUDE_yescrypt
384 # define EXPECTED_DEFAULT_PREFIX "$y$"
385 #elif INCLUDE_bcrypt
386 # define EXPECTED_DEFAULT_PREFIX "$2b$"
387 #elif INCLUDE_sha512crypt
388 # define EXPECTED_DEFAULT_PREFIX "$6$"
389 #endif
390
391 #if CRYPT_GENSALT_IMPLEMENTS_DEFAULT_PREFIX
392 # ifndef EXPECTED_DEFAULT_PREFIX
393 # error "Which hashing algorithm is the default?"
394 # endif
395 #else
396 # ifdef EXPECTED_DEFAULT_PREFIX
397 # error "Default hashing algorithm should be available"
398 # endif
399 #endif
400
401 int
402 main (void)
403 {
404 int status = 0;
405 unsigned int ent;
406 const struct testcase *tcase;
407 char output[CRYPT_GENSALT_OUTPUT_SIZE];
408 char prev_output[CRYPT_GENSALT_OUTPUT_SIZE];
409
410 for (tcase = testcases; tcase->prefix; tcase++)
411 {
412 memset (prev_output, 0, CRYPT_GENSALT_OUTPUT_SIZE);
413 for (ent = 0; ent < ARRAY_SIZE (entropy); ent++)
414 {
415 memset (output, 0, CRYPT_GENSALT_OUTPUT_SIZE);
416 char *salt = crypt_gensalt_rn (tcase->prefix, tcase->rounds,
417 entropy[ent], 16,
418 output, CRYPT_GENSALT_OUTPUT_SIZE);
419 if (salt == 0)
420 {
421 if (entropy[ent] == 0 && errno == ENOSYS)
422 {
423 fprintf (stderr,
424 "UNSUPPORTED: %s/%lu/auto-entropy -> ENOSYS\n",
425 tcase->prefix, tcase->rounds);
426 }
427 else
428 {
429 fprintf (stderr, "ERROR: %s/%lu/%u -> 0\n",
430 tcase->prefix, tcase->rounds, ent);
431 status = 1;
432 }
433 continue;
434 }
435 size_t slen = strlen (salt);
436 unsigned int expected_len =
437 (!entropy[ent] && tcase->expected_auto_len) ?
438 tcase->expected_auto_len : tcase->expected_len;
439 if (slen != expected_len)
440 {
441 fprintf (stderr,
442 "ERROR: %s/%lu/%u -> %s (expected len=%u got %zu)\n",
443 tcase->prefix, tcase->rounds, ent, salt,
444 expected_len, slen);
445 status = 1;
446 }
447 else if (strncmp (salt, tcase->prefix, strlen (tcase->prefix)))
448 {
449 fprintf (stderr, "ERROR: %s/%lu/%u -> %s (prefix wrong)\n",
450 tcase->prefix, tcase->rounds, ent, salt);
451 status = 1;
452 }
453 else if (!strcmp (salt, prev_output))
454 {
455 fprintf (stderr, "ERROR: %s/%lu/%u -> %s (same as prev)\n",
456 tcase->prefix, tcase->rounds, ent, salt);
457 status = 1;
458 }
459 else if (entropy[ent] && strcmp (salt, tcase->expected_output[ent]))
460 {
461 fprintf (stderr, "ERROR: %s/%lu/%u -> %s (expected %s)\n",
462 tcase->prefix, tcase->rounds, ent, salt,
463 tcase->expected_output[ent]);
464 status = 1;
465 }
466 else
467 fprintf (stderr, " ok: %s/%lu/%u -> %s\n",
468 tcase->prefix, tcase->rounds, ent, salt);
469
470 strcpy_or_abort (prev_output, CRYPT_GENSALT_OUTPUT_SIZE, salt);
471
472 /* Test if crypt works with this salt. */
473 if (!tcase->rounds)
474 {
475 #define PASSW "alexander"
476 static struct crypt_data a, b;
477 if (!crypt_rn (PASSW, salt, &a, sizeof(a)))
478 {
479 fprintf (stderr, "ERROR: %s/%u -> crypt(gensalt) fail\n",
480 tcase->prefix, ent);
481 status = 1;
482 }
483 else if (!crypt_rn (PASSW, a.output, &b, sizeof(b)))
484 {
485 fprintf (stderr, "ERROR: %s/%u -> crypt(crypt(gensalt)) fail\n",
486 tcase->prefix, ent);
487 status = 1;
488 }
489 else if (strcmp (a.output, b.output))
490 {
491 fprintf (stderr, "ERROR: %s/%u -> crypt(gensalt) != crypt(crypt(gensalt))\n",
492 tcase->prefix, ent);
493 status = 1;
494 }
495 else
496 {
497 fprintf (stderr, " ok: %s/%u -> crypt works with this salt\n",
498 tcase->prefix, ent);
499 }
500 }
501 }
502 }
503 #if CRYPT_GENSALT_IMPLEMENTS_DEFAULT_PREFIX
504 /* Passing a null pointer as the prefix argument to crypt_gensalt is
505 supposed to tell it to use the "best available" hashing method. */
506 {
507 char *setting1, *setting2;
508 setting1 = crypt_gensalt_ra (EXPECTED_DEFAULT_PREFIX, 0, entropy[0], 16);
509 setting2 = crypt_gensalt_ra (0, 0, entropy[0], 16);
510 if ((setting1 == 0 && setting2 != 0) ||
511 (setting1 != 0 && setting2 == 0) ||
512 (setting1 != 0 && setting2 != 0 && strcmp (setting1, setting2)))
513 {
514 printf ("FAILED: crypt_gensalt defaulting to $y$\n"
515 " $y$ -> %s\n"
516 " null -> %s\n",
517 setting1, setting2);
518 status = 1;
519 }
520 free (setting1);
521 free (setting2);
522 }
523 #else
524 {
525 char *setting = crypt_gensalt_ra (0, 0, entropy[0], 16);
526 if (setting)
527 {
528 printf ("FAILED: crypt_gensalt null -> %s (null expected)\n", setting);
529 status = 1;
530 }
531 free (setting);
532 }
533 #endif
534 return status;
535 }