1 /* Copyright (C) 2018-2021 Björn Esser <besser82@fedoraproject.org>
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted.
5 *
6 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
7 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
10 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
11 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
15 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
16 * SUCH DAMAGE.
17 */
18
19 #include "crypt-port.h"
20 #include <stdio.h>
21
22 struct testcase
23 {
24 const char *prefix;
25 const int exp_prefix;
26 const int exp_gensalt;
27 const int exp_crypt;
28 };
29
30 static const struct testcase testcases[] =
31 {
32 #if INCLUDE_descrypt || INCLUDE_bigcrypt
33 { "", CRYPT_SALT_INVALID, CRYPT_SALT_METHOD_LEGACY, CRYPT_SALT_METHOD_LEGACY },
34 { "..", CRYPT_SALT_METHOD_LEGACY, CRYPT_SALT_METHOD_LEGACY, CRYPT_SALT_METHOD_LEGACY },
35 { "MN", CRYPT_SALT_METHOD_LEGACY, CRYPT_SALT_METHOD_LEGACY, CRYPT_SALT_METHOD_LEGACY },
36 #else
37 { "", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
38 { "..", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
39 { "MN", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
40 #endif
41 #if INCLUDE_bsdicrypt
42 { "_", CRYPT_SALT_METHOD_LEGACY, CRYPT_SALT_METHOD_LEGACY, CRYPT_SALT_METHOD_LEGACY },
43 #else
44 { "_", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
45 #endif
46 #if INCLUDE_md5crypt
47 { "$1$", CRYPT_SALT_METHOD_LEGACY, CRYPT_SALT_METHOD_LEGACY, CRYPT_SALT_METHOD_LEGACY },
48 #else
49 { "$1$", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
50 #endif
51 #if INCLUDE_nt
52 { "$3$", CRYPT_SALT_METHOD_LEGACY, CRYPT_SALT_METHOD_LEGACY, CRYPT_SALT_METHOD_LEGACY },
53 #else
54 { "$3$", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
55 #endif
56 #if INCLUDE_sunmd5
57 { "$md5", CRYPT_SALT_METHOD_LEGACY, CRYPT_SALT_METHOD_LEGACY, CRYPT_SALT_METHOD_LEGACY },
58 #else
59 { "$md5", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
60 #endif
61 #if INCLUDE_sha1crypt
62 { "$sha1", CRYPT_SALT_METHOD_LEGACY, CRYPT_SALT_METHOD_LEGACY, CRYPT_SALT_METHOD_LEGACY },
63 #else
64 { "$sha1", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
65 #endif
66 #if INCLUDE_sha256crypt
67 { "$5$", CRYPT_SALT_METHOD_LEGACY, CRYPT_SALT_METHOD_LEGACY, CRYPT_SALT_METHOD_LEGACY },
68 #else
69 { "$5$", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
70 #endif
71 #if INCLUDE_sha512crypt
72 { "$6$", CRYPT_SALT_OK, CRYPT_SALT_OK, CRYPT_SALT_OK },
73 #else
74 { "$6$", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
75 #endif
76 #if INCLUDE_bcrypt
77 { "$2b$", CRYPT_SALT_OK, CRYPT_SALT_OK, CRYPT_SALT_OK },
78 #else
79 { "$2b$", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
80 #endif
81 #if INCLUDE_bcrypt_a
82 { "$2a$", CRYPT_SALT_OK, CRYPT_SALT_OK, CRYPT_SALT_OK },
83 #else
84 { "$2a$", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
85 #endif
86 #if INCLUDE_bcrypt_x
87 { "$2x$", CRYPT_SALT_METHOD_LEGACY, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
88 #else
89 { "$2x$", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
90 #endif
91 #if INCLUDE_bcrypt_y
92 { "$2y$", CRYPT_SALT_OK, CRYPT_SALT_OK, CRYPT_SALT_OK },
93 #else
94 { "$2y$", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
95 #endif
96 #if INCLUDE_yescrypt
97 { "$y$", CRYPT_SALT_OK, CRYPT_SALT_OK, CRYPT_SALT_OK },
98 #else
99 { "$y$", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
100 #endif
101 #if INCLUDE_scrypt
102 { "$7$", CRYPT_SALT_OK, CRYPT_SALT_OK, CRYPT_SALT_OK },
103 #else
104 { "$7$", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
105 #endif
106 #if INCLUDE_gost_yescrypt
107 { "$gy$", CRYPT_SALT_OK, CRYPT_SALT_OK, CRYPT_SALT_OK },
108 #else
109 { "$gy$", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
110 #endif
111
112 /* All of these are invalid. */
113 { "$@", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
114 { "%A", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
115 { "A%", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
116 { "$2$", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
117 { "*0", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
118 { "*1", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
119 { " ", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
120 { "!!", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
121 { "**", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
122 { "::", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
123 { ";;", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
124 { "\\\\", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
125 { "\x01\x01", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
126 { "\x19\x19", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
127 { "\x20\x20", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
128 { "\x7f\x7f", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
129 { "\xfe\xfe", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
130 { "\xff\xff", CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
131 #if defined HASH_ALGORITHM_DEFAULT
132 { NULL, CRYPT_SALT_INVALID, CRYPT_SALT_OK, CRYPT_SALT_OK },
133 #else
134 { NULL, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID, CRYPT_SALT_INVALID },
135 #endif
136 };
137
138 int
139 main (void)
140 {
141 char gs_out[CRYPT_GENSALT_OUTPUT_SIZE] = "";
142 const char *phr = "police saying freeze";
143 struct crypt_data cd;
144 const size_t gs_len = CRYPT_GENSALT_OUTPUT_SIZE;
145
146 int status = 0;
147 int retval = 0;
148
149 for (size_t i = 0; i < ARRAY_SIZE (testcases); i++)
150 {
151 /* crypt_checksalt on prefix. */
152 retval = crypt_checksalt (testcases[i].prefix);
153 if (retval == testcases[i].exp_prefix)
154 printf ("PASS (prefix): %s, result: %d\n",
155 testcases[i].prefix, retval);
156 else
157 {
158 status = 1;
159 printf ("FAIL (prefix): %s, expected: %d, got: %d\n",
160 testcases[i].prefix,
161 testcases[i].exp_prefix, retval);
162 continue;
163 }
164
165 /* crypt_checksalt on gensalt output. */
166 crypt_gensalt_rn (testcases[i].prefix, 0, NULL, 0,
167 gs_out, (int) gs_len);
168 retval = crypt_checksalt (gs_out);
169 if (retval == testcases[i].exp_gensalt)
170 printf ("PASS (gensalt): %s, result: %d\n",
171 gs_out, retval);
172 else
173 {
174 status = 1;
175 printf ("FAIL (gensalt): %s, expected: %d, got: %d\n",
176 gs_out, testcases[i].exp_gensalt, retval);
177 continue;
178 }
179
180 /* crypt_checksalt on crypt output. */
181 crypt_r (phr, gs_out, &cd);
182 retval = crypt_checksalt (cd.output);
183 if (retval == testcases[i].exp_crypt)
184 printf ("PASS (crypt): %s, result: %d\n",
185 cd.output, retval);
186 else
187 {
188 status = 1;
189 printf ("FAIL (crypt): %s, expected: %d, got: %d\n",
190 cd.output, testcases[i].exp_crypt, retval);
191 }
192
193 #if INCLUDE_descrypt && INCLUDE_bigcrypt
194
195 /* Test bigcrypt as well. */
196 if (testcases[i].prefix && strlen (testcases[i].prefix) == 2)
197 {
198 /* Prefix must be at least 14 bytes. */
199 char bigcrypt_prefix[CRYPT_GENSALT_OUTPUT_SIZE];
200 const char *pad = "............";
201 memcpy (bigcrypt_prefix, testcases[i].prefix, 2);
202 strncpy (bigcrypt_prefix + 2, pad, gs_len - 2);
203
204 /* crypt_checksalt on prefix. */
205 retval = crypt_checksalt (bigcrypt_prefix);
206 if (retval == testcases[i].exp_prefix)
207 printf ("PASS (prefix): %s, result: %d\n",
208 bigcrypt_prefix, retval);
209 else
210 {
211 status = 1;
212 printf ("FAIL (prefix): %s, expected: %d, got: %d\n",
213 bigcrypt_prefix,
214 testcases[i].exp_prefix, retval);
215 continue;
216 }
217
218 /* crypt_checksalt on gensalt output. */
219 crypt_gensalt_rn (bigcrypt_prefix, 0, NULL, 0,
220 gs_out, (int) gs_len);
221
222 /* Add 12 trailing bytes. */
223 strncpy (gs_out + 2, pad, gs_len - 2);
224
225 retval = crypt_checksalt (gs_out);
226 if (retval == testcases[i].exp_gensalt)
227 printf ("PASS (gensalt): %s, result: %d\n",
228 gs_out, retval);
229 else
230 {
231 status = 1;
232 printf ("FAIL (gensalt): %s, expected: %d, got: %d\n",
233 gs_out, testcases[i].exp_gensalt, retval);
234 continue;
235 }
236
237 /* crypt_checksalt on crypt output. */
238 crypt_r (phr, gs_out, &cd);
239 retval = crypt_checksalt (cd.output);
240 if (retval == testcases[i].exp_crypt)
241 printf ("PASS (crypt): %s, result: %d\n",
242 cd.output, retval);
243 else
244 {
245 status = 1;
246 printf ("FAIL (crypt): %s, expected: %d, got: %d\n",
247 cd.output, testcases[i].exp_crypt, retval);
248 }
249 }
250 #endif
251
252 }
253
254 return status;
255 }