1 /*
2 * Description from Nicolas Ruff:
3 * - Salt value is hashed as an hexadecimal string, not bytes.
4 * - The trailing NULL byte of password string is taken into account during
5 * hashing.
6 * - The leading '1' is actually the string length
7 * '1' = 49 = len('1') + len(hex_salt) + len(hex_sha1)
8 *
9 * ---------------------------------------
10 * import hashlib
11 *
12 * def netscaler_hash( rand_bytes, pwd ):
13 * s = hashlib.sha1()
14 * s.update( rand_bytes )
15 * s.update( pwd )
16 * return "1" + rand_bytes + s.hexdigest()
17 *
18 * # TEST VECTOR
19 * # 14dfca1e6c0f5f3d96526c3ce70849992b7fad3e324cf6b0f
20 *
21 * rand_bytes = "4dfca1e6"
22 * pwd = "nsroot\x00"
23 * print netscaler_hash( rand_bytes, pwd )
24 * ---------------------------------------
25 *
26 * This software is Copyright (c) 2013 magnum, and it is hereby released to the
27 * general public under the following terms: Redistribution and use in source
28 * and binary forms, with or without modification, are permitted.
29 *
30 * This version is hard coded for salt length 8 (for speed).
31 */
32
33 #if FMT_EXTERNS_H
34 extern struct fmt_main fmt_ctrxns;
35 #elif FMT_REGISTERS_H
36 john_register_one(&fmt_ctrxns);
37 #else
38
39 #include <string.h>
40
41 #ifdef _OPENMP
42 #include <omp.h>
43 #endif
44
45 #include "arch.h"
46 #include "misc.h"
47 #include "formats.h"
48 #include "options.h"
49 #include "johnswap.h"
50
51 #ifdef SIMD_COEF_32
52 #define NBKEYS (SIMD_COEF_32 * SIMD_PARA_SHA1)
53 #endif
54 #include "simd-intrinsics.h"
55 #include "common.h"
56 #include "sha.h"
57
58 #define FORMAT_LABEL "Citrix_NS10"
59 #define FORMAT_NAME "Netscaler 10"
60
61 #define ALGORITHM_NAME "SHA1 " SHA1_ALGORITHM_NAME
62
63 #define BENCHMARK_COMMENT ""
64 #define BENCHMARK_LENGTH 7
65
66 #define PLAINTEXT_LENGTH (55 - SALT_SIZE - 1)
67
68 #define BINARY_SIZE 20
69 #define BINARY_ALIGN 4
70 #define SALT_SIZE 8
71 #define SALT_ALIGN 4
72
73 #ifdef SIMD_COEF_32
74 #define MIN_KEYS_PER_CRYPT NBKEYS
75 #define MAX_KEYS_PER_CRYPT (NBKEYS * 256)
76 #define FMT_IS_BE
77 #include "common-simd-getpos.h"
78 #else
79 #define MIN_KEYS_PER_CRYPT 1
80 #define MAX_KEYS_PER_CRYPT 256
81 #endif
82
83 #ifndef OMP_SCALE
84 #define OMP_SCALE 4 // Tuned w/ MKPC for core i7
85 #endif
86
87 static struct fmt_tests tests[] = {
88 {"100000000f1dc96f425971ba590a076fd0f8bccbf25c1ba0c", ""},
89 {"14623718525fe334bbd9c0704e06ce134ef17b51f6b33548c", " "},
90 {"15c5c5c5c6ccd884f6383f55a6aeba5f847775e57ab012675", "Tw"},
91 {"13333333319143136ba9ff9e18d1cb022b63df0926de9509e", "333"},
92 {"144434241d7ce89a7484cd202400639692258dde37efc29c5", "four"},
93 {"100010203e09cefed1847b7a2a5e7a5d2cdc67e8a56ed0bdd", "fiver"},
94 {"14dfca1e6c0f5f3d96526c3ce70849992b7fad3e324cf6b0f", "nsroot"},
95 {"1deadcafe7587ea23b25a6ccf3fd53192e36ad3e9a2553b20", "magnum!"},
96 {NULL}
97 };
98
99 #ifdef SIMD_COEF_32
100 static unsigned char (*saved_key)[SHA_BUF_SIZ * 4 * NBKEYS];
101 static unsigned char (*crypt_key)[BINARY_SIZE * NBKEYS];
102 static unsigned int kpc;
103 #else
104 static char saved_salt[SALT_SIZE];
105 static char (*saved_key)[PLAINTEXT_LENGTH + 1];
106 static uint32_t (*crypt_key)[BINARY_SIZE / 4];
107 #endif
108
init(struct fmt_main * self)109 static void init(struct fmt_main *self)
110 {
111 omp_autotune(self, OMP_SCALE);
112
113 #ifdef SIMD_COEF_32
114 saved_key = mem_calloc_align(self->params.max_keys_per_crypt / NBKEYS,
115 sizeof(*saved_key), MEM_ALIGN_SIMD);
116 crypt_key = mem_calloc_align(self->params.max_keys_per_crypt / NBKEYS,
117 sizeof(*crypt_key), MEM_ALIGN_SIMD);
118 kpc = self->params.max_keys_per_crypt;
119 #else
120 saved_key = mem_calloc(self->params.max_keys_per_crypt,
121 sizeof(*saved_key));
122 crypt_key = mem_calloc(self->params.max_keys_per_crypt,
123 sizeof(*crypt_key));
124 #endif
125 }
126
done(void)127 static void done(void)
128 {
129 MEM_FREE(crypt_key);
130 MEM_FREE(saved_key);
131 }
132
get_binary(char * ciphertext)133 static void *get_binary(char *ciphertext)
134 {
135 static unsigned char *realcipher;
136 int i, len;
137
138 if (!realcipher)
139 realcipher = mem_alloc_tiny(BINARY_SIZE, MEM_ALIGN_WORD);
140
141 len = *ciphertext;
142
143 ciphertext += len - 2 * BINARY_SIZE;
144
145 for (i = 0; i < BINARY_SIZE; i++)
146 {
147 realcipher[i] = atoi16[ARCH_INDEX(ciphertext[i * 2])] * 16
148 + atoi16[ARCH_INDEX(ciphertext[i * 2 + 1])];
149 }
150 #if defined(SIMD_COEF_32) && ARCH_LITTLE_ENDIAN==1
151 alter_endianity(realcipher, BINARY_SIZE);
152 #endif
153 return (void*)realcipher;
154 }
155
valid(char * ciphertext,struct fmt_main * self)156 static int valid(char *ciphertext, struct fmt_main *self)
157 {
158 int len;
159
160 len = *ciphertext;
161
162 if (len != (int)'1')
163 return 0;
164
165 if (strlen(ciphertext) != len)
166 return 0;
167
168 if (len != strspn(ciphertext, HEXCHARS_lc))
169 return 0;
170
171 return 1;
172 }
173
174 // this is a salt appended format. It also 'keeps' the trailing null byte.
175 #define SALT_PREPENDED SALT_SIZE
176 #define INCLUDE_TRAILING_NULL
177 #include "common-simd-setkey32.h"
178
get_salt(char * ciphertext)179 static void *get_salt(char *ciphertext)
180 {
181 static union {
182 unsigned char c[SALT_SIZE];
183 uint32_t w;
184 } out;
185
186 ciphertext++;
187 memcpy(out.c, ciphertext, SALT_SIZE);
188
189 return (void*)out.c;
190 }
191
set_salt(void * salt)192 static void set_salt(void *salt)
193 {
194 #ifdef SIMD_COEF_32
195 int i, index;
196
197 for (index = 0; index < kpc; index++) {
198 int idx = index % NBKEYS;
199 unsigned char *sk = saved_key[index/NBKEYS];
200 for (i = 0; i < SALT_SIZE; i++)
201 sk[GETPOS(i, idx)] = ((unsigned char*)salt)[i];
202 }
203 #else
204 memcpy(saved_salt, salt, SALT_SIZE);
205 #endif
206 }
207
cmp_all(void * binary,int count)208 static int cmp_all(void *binary, int count)
209 {
210 #ifdef SIMD_COEF_32
211 unsigned int x, y;
212
213 for (y = 0; y < kpc/SIMD_COEF_32; y++) {
214 for (x = 0; x < SIMD_COEF_32; x++) {
215 if (((uint32_t*)binary)[0] ==
216 ((uint32_t*)crypt_key)[x + y * SIMD_COEF_32*5])
217 return 1;
218 }
219 }
220
221 return 0;
222 #else
223 int index;
224
225 for (index = 0; index < count; index++)
226 if (((uint32_t*)binary)[0] == crypt_key[index][0])
227 return 1;
228
229 return 0;
230 #endif
231 }
232
cmp_one(void * binary,int index)233 static int cmp_one(void *binary, int index)
234 {
235 #ifdef SIMD_COEF_32
236 unsigned int x, y;
237 x = index & (SIMD_COEF_32-1);
238 y = (unsigned int)index / SIMD_COEF_32;
239
240 if (((uint32_t*)binary)[0] != ((uint32_t*)crypt_key)[x + y * SIMD_COEF_32*5])
241 return 0;
242 if (((uint32_t*)binary)[1] != ((uint32_t*)crypt_key)[x + y * SIMD_COEF_32*5+SIMD_COEF_32*1])
243 return 0;
244 if (((uint32_t*)binary)[2] != ((uint32_t*)crypt_key)[x + y * SIMD_COEF_32*5+SIMD_COEF_32*2])
245 return 0;
246 if (((uint32_t*)binary)[3] != ((uint32_t*)crypt_key)[x + y * SIMD_COEF_32*5+SIMD_COEF_32*3])
247 return 0;
248 if (((uint32_t*)binary)[4] != ((uint32_t*)crypt_key)[x + y * SIMD_COEF_32*5+SIMD_COEF_32*4])
249 return 0;
250 return 1;
251 #else
252 return !memcmp(binary, crypt_key[index], BINARY_SIZE);
253 #endif
254 }
255
cmp_exact(char * source,int index)256 static int cmp_exact(char *source, int index)
257 {
258 return 1;
259 }
260
crypt_all(int * pcount,struct db_salt * salt)261 static int crypt_all(int *pcount, struct db_salt *salt)
262 {
263 const int count = *pcount;
264 int index;
265 int loops = (count + MIN_KEYS_PER_CRYPT - 1) / MIN_KEYS_PER_CRYPT;
266
267 #ifdef _OPENMP
268 #pragma omp parallel for
269 #endif
270 for (index = 0; index < loops; ++index) {
271 #ifdef SIMD_COEF_32
272 SIMDSHA1body(saved_key[index], (unsigned int*)crypt_key[index], NULL, SSEi_MIXED_IN);
273 #else
274 SHA_CTX ctx;
275
276 SHA1_Init(&ctx);
277 SHA1_Update(&ctx, (unsigned char*)saved_salt, SALT_SIZE);
278 SHA1_Update(&ctx, (unsigned char*)saved_key[index], strlen(saved_key[index]) + 1);
279 SHA1_Final((unsigned char*)crypt_key[index], &ctx);
280 #endif
281 }
282
283 return count;
284 }
285
286 #define COMMON_GET_HASH_SIMD32 5
287 #define COMMON_GET_HASH_VAR crypt_key
288 #include "common-get-hash.h"
289
salt_hash(void * salt)290 static int salt_hash(void *salt)
291 {
292 return *(uint32_t*)salt & (SALT_HASH_SIZE - 1);
293 }
294
295 struct fmt_main fmt_ctrxns = {
296 {
297 FORMAT_LABEL,
298 FORMAT_NAME,
299 ALGORITHM_NAME,
300 BENCHMARK_COMMENT,
301 BENCHMARK_LENGTH,
302 0,
303 PLAINTEXT_LENGTH,
304 BINARY_SIZE,
305 BINARY_ALIGN,
306 SALT_SIZE,
307 SALT_ALIGN,
308 MIN_KEYS_PER_CRYPT,
309 MAX_KEYS_PER_CRYPT,
310 FMT_CASE | FMT_8_BIT | FMT_OMP | FMT_OMP_BAD,
311 { NULL },
312 { NULL },
313 tests
314 }, {
315 init,
316 done,
317 fmt_default_reset,
318 fmt_default_prepare,
319 valid,
320 fmt_default_split,
321 get_binary,
322 get_salt,
323 { NULL },
324 fmt_default_source,
325 {
326 fmt_default_binary_hash_0,
327 fmt_default_binary_hash_1,
328 fmt_default_binary_hash_2,
329 fmt_default_binary_hash_3,
330 fmt_default_binary_hash_4,
331 fmt_default_binary_hash_5,
332 fmt_default_binary_hash_6
333 },
334 salt_hash,
335 NULL,
336 set_salt,
337 set_key,
338 get_key,
339 fmt_default_clear_keys,
340 crypt_all,
341 {
342 #define COMMON_GET_HASH_LINK
343 #include "common-get-hash.h"
344 },
345 cmp_all,
346 cmp_one,
347 cmp_exact
348 }
349 };
350
351 #endif /* plugin stanza */
352