1 /*
2  * This software is Copyright (c) 2017, Dhiru Kholia <dhiru.kholia at gmail.com>,
3  * and it is hereby released to the general public under the following terms:
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted.
7  *
8  * References,
9  *
10  * https://tools.ietf.org/html/rfc5802
11  * https://tools.ietf.org/html/rfc7677
12  * https://wiki.xmpp.org/web/SASLandSCRAM-SHA-1
13  *
14  * Hash format -> $scram$0$iterations$salt-len$salt-in-hex$hash
15  */
16 
17 #if FMT_EXTERNS_H
18 extern struct fmt_main fmt_xmpp_scram;
19 #elif FMT_REGISTERS_H
20 john_register_one(&fmt_xmpp_scram);
21 #else
22 
23 #include <string.h>
24 
25 #ifdef _OPENMP
26 #include <omp.h>
27 #endif
28 
29 #include "arch.h"
30 #include "misc.h"
31 #include "memory.h"
32 #include "common.h"
33 #include "formats.h"
34 #include "johnswap.h"
35 #include "sha.h"
36 #include "hmac_sha.h"
37 #include "simd-intrinsics.h"
38 #include "pbkdf2_hmac_sha1.h"
39 
40 #if defined SIMD_COEF_32
41 #define SIMD_KEYS               (SIMD_COEF_32 * SIMD_PARA_SHA1)
42 #endif
43 
44 #define FORMAT_LABEL            "xmpp-scram"
45 #define FORMAT_NAME             ""
46 #define ALGORITHM_NAME          "XMPP SCRAM PBKDF2-SHA1 " SHA1_ALGORITHM_NAME
47 #define PLAINTEXT_LENGTH        125
48 #define HASH_LENGTH             28
49 #define SALT_SIZE               sizeof(struct custom_salt)
50 #define SALT_ALIGN              sizeof(uint32_t)
51 #define BINARY_SIZE             20
52 #define BINARY_ALIGN            sizeof(uint32_t)
53 #define BENCHMARK_COMMENT       ""
54 #define BENCHMARK_LENGTH        0x107
55 #define FORMAT_TAG              "$xmpp-scram$"
56 #define FORMAT_TAG_LENGTH       (sizeof(FORMAT_TAG) - 1)
57 
58 #if !defined(SIMD_COEF_32)
59 #define MIN_KEYS_PER_CRYPT      1
60 #define MAX_KEYS_PER_CRYPT      4
61 #else
62 #define MIN_KEYS_PER_CRYPT      SIMD_KEYS
63 #define MAX_KEYS_PER_CRYPT      (SIMD_KEYS * 2)
64 #endif
65 
66 #ifndef OMP_SCALE
67 #define OMP_SCALE               16 // Tuned w/ MKPC for core i7
68 #endif
69 
70 static struct fmt_tests tests[] = {
71 	// hash generated by prosody-0.9.12 (taken from a .dat file)
72 	{"$xmpp-scram$0$4096$36$37333536663261622d613666622d346333642d396232622d626432646237633338343064$38f79a6e3e64c07f731570d531ec05365aa05306", "openwall123"},
73 	// ejabberd-16.01 generated hash from "ejabberdctl dump output.txt" processed with ejabberd2john.py
74 	{"$xmpp-scram$0$4096$16$4f67aec1bd53f5f2f74652e69a3b8f32$4aec3caa8ace5180efa7a671092646c041ab1496", "qwerty"},
75 	// ejabberd hash with a space in password
76 	{"$xmpp-scram$0$4096$16$1f7fcb384d5bcc61dfb1231ae1b32a2f$a2d076d56b0152ed557ad7d38fce93159bc63c9b", "password 123"},
77 	// openfire 4.1.6 hash, manually extracted from the database
78 	{"$xmpp-scram$0$4096$24$bc1bd6638a1231ffd54f608983425eacf729d8455a469197$aee9254762b23a3950fd7c803caab5f6654587c8", "openwall123"},
79 	{NULL}
80 };
81 
82 static struct custom_salt {
83 	uint32_t saltlen;
84 	uint32_t iterations;
85 	uint32_t type;
86 	unsigned char salt[64+1];
87 } *cur_salt;
88 
89 static char (*saved_key)[PLAINTEXT_LENGTH + 1];
90 static uint32_t (*crypt_out)[BINARY_SIZE / sizeof(uint32_t)];
91 
init(struct fmt_main * self)92 static void init(struct fmt_main *self)
93 {
94 	omp_autotune(self, OMP_SCALE);
95 
96 	saved_key = mem_calloc(self->params.max_keys_per_crypt,
97 			sizeof(*saved_key));
98 	crypt_out = mem_calloc(self->params.max_keys_per_crypt,
99 			sizeof(*crypt_out));
100 }
101 
done(void)102 static void done(void)
103 {
104 	MEM_FREE(crypt_out);
105 	MEM_FREE(saved_key);
106 }
107 
valid(char * ciphertext,struct fmt_main * self)108 static int valid(char *ciphertext, struct fmt_main *self)
109 {
110 	char *ctcopy, *keeptr, *p;
111 	int res, extra;
112 
113 	if (strncmp(ciphertext, FORMAT_TAG, FORMAT_TAG_LENGTH) != 0)
114 		return 0;
115 	ctcopy = strdup(ciphertext);
116 	keeptr = ctcopy;
117 	ctcopy += FORMAT_TAG_LENGTH;
118 	if ((p = strtokm(ctcopy, "$")) == NULL)	/* internal type */
119 		goto err;
120 	if (!isdec(p))
121 		goto err;
122 	if (atoi(p) != 0)
123 		goto err;
124 	if ((p = strtokm(NULL, "$")) == NULL)	/* iterations */
125 		goto err;
126 	if (!isdec(p))
127 		goto err;
128 	if ((p = strtokm(NULL, "$")) == NULL)	/* salten */
129 		goto err;
130 	if (!isdec(p))
131 		goto err;
132 	res = atoi(p);
133 	if (res > 64)
134 		goto err;
135 	if ((p = strtokm(NULL, "$")) == NULL)	/* salt */
136 		goto err;
137 	if (hexlenl(p, &extra) != res * 2 || extra)
138 		goto err;
139 	if ((p = strtokm(NULL, "$")) == NULL)	/* hash */
140 		goto err;
141 	if (hexlenl(p, &extra) != BINARY_SIZE * 2 || extra)
142 		goto err;
143 
144 	MEM_FREE(keeptr);
145 	return 1;
146 
147 err:
148 	MEM_FREE(keeptr);
149 	return 0;
150 }
151 
get_salt(char * ciphertext)152 static void *get_salt(char *ciphertext)
153 {
154 	static struct custom_salt cs;
155 	char *ctcopy, *keeptr, *p;
156 	int i;
157 
158 	memset(&cs, 0, sizeof(cs));
159 	ctcopy = strdup(ciphertext);
160 	keeptr = ctcopy;;
161 	ctcopy += FORMAT_TAG_LENGTH;
162 	p = strtokm(ctcopy, "$");
163 	cs.type = atoi(p);
164 	p = strtokm(NULL, "$");
165 	cs.iterations = atoi(p);
166 	p = strtokm(NULL, "$");
167 	cs.saltlen = atoi(p);
168 	p = strtokm(NULL, "$");
169 	for (i = 0; i < cs.saltlen; i++) {
170 		cs.salt[i] = (atoi16[ARCH_INDEX(*p)] << 4) | atoi16[ARCH_INDEX(p[1])];
171 		p += 2;
172 	}
173 
174 	MEM_FREE(keeptr);
175 
176 	return (void *)&cs;
177 }
178 
get_binary(char * ciphertext)179 static void *get_binary(char *ciphertext)
180 {
181 	static union {
182 		unsigned char c[BINARY_SIZE + 1];
183 		ARCH_WORD dummy;
184 	} buf;
185 	unsigned char *out = buf.c;
186 	char *p;
187 	int i;
188 
189 	p = strrchr(ciphertext, '$') + 1;
190 	for (i = 0; i < BINARY_SIZE; i++) {
191 		out[i] = (atoi16[ARCH_INDEX(*p)] << 4) | atoi16[ARCH_INDEX(p[1])];
192 		p += 2;
193 	}
194 
195 	return out;
196 }
197 
set_salt(void * salt)198 static void set_salt(void *salt)
199 {
200 	cur_salt = (struct custom_salt *)salt;
201 }
202 
203 #define COMMON_GET_HASH_VAR crypt_out
204 #include "common-get-hash.h"
205 
crypt_all(int * pcount,struct db_salt * salt)206 static int crypt_all(int *pcount, struct db_salt *salt)
207 {
208 	int index;
209 	const int count = *pcount;
210 
211 #ifdef _OPENMP
212 #pragma omp parallel for
213 #endif
214 	for (index = 0; index < count; index += MIN_KEYS_PER_CRYPT) {
215 #if !defined (SIMD_COEF_32)
216 		unsigned char out[BINARY_SIZE];
217 		SHA_CTX ctx;
218 
219 		pbkdf2_sha1((unsigned char*)saved_key[index],
220 				strlen(saved_key[index]), cur_salt->salt,
221 				cur_salt->saltlen, cur_salt->iterations, out,
222 				BINARY_SIZE, 0);
223 
224 		hmac_sha1(out, BINARY_SIZE, (unsigned char*)"Client Key", 10, out, BINARY_SIZE);
225 		SHA1_Init(&ctx);
226 		SHA1_Update(&ctx, out, BINARY_SIZE);
227 		SHA1_Final((unsigned char*)crypt_out[index], &ctx);
228 #else
229 		SHA_CTX ctx;
230 		int i;
231 		unsigned char *pin[SIMD_KEYS];
232 		int lens[SIMD_KEYS];
233 		unsigned char out_[SIMD_KEYS][BINARY_SIZE], *out[SIMD_KEYS];
234 
235 		for (i = 0; i < SIMD_KEYS; ++i) {
236 			pin[i] = (unsigned char*)saved_key[index+i];
237 			lens[i] = strlen(saved_key[index+i]);
238 			out[i] = out_[i];
239 		}
240 
241 		pbkdf2_sha1_sse((const unsigned char **)pin, lens, cur_salt->salt,
242 			cur_salt->saltlen, cur_salt->iterations, out,
243 			BINARY_SIZE, 0);
244 
245 		for (i = 0; i < SIMD_KEYS; ++i) {
246 			hmac_sha1(out[i], BINARY_SIZE, (unsigned char*)"Client Key", 10, out[i], BINARY_SIZE);
247 			SHA1_Init(&ctx);
248 			SHA1_Update(&ctx, out[i], BINARY_SIZE);
249 			SHA1_Final((unsigned char*)crypt_out[index+i], &ctx);
250 		}
251 #endif
252 	}
253 	return count;
254 }
255 
cmp_all(void * binary,int count)256 static int cmp_all(void *binary, int count)
257 {
258 	int index;
259 
260 	for (index = 0; index < count; index++)
261 		if (!memcmp(binary, crypt_out[index], ARCH_SIZE))
262 			return 1;
263 	return 0;
264 }
265 
cmp_one(void * binary,int index)266 static int cmp_one(void *binary, int index)
267 {
268 	return !memcmp(binary, crypt_out[index], BINARY_SIZE);
269 }
270 
cmp_exact(char * source,int index)271 static int cmp_exact(char *source, int index)
272 {
273 	return 1;
274 }
275 
set_key(char * key,int index)276 static void set_key(char *key, int index)
277 {
278 	strnzcpy(saved_key[index], key, sizeof(*saved_key));
279 }
280 
get_key(int index)281 static char *get_key(int index)
282 {
283 	return saved_key[index];
284 }
285 
286 struct fmt_main fmt_xmpp_scram = {
287 	{
288 		FORMAT_LABEL,
289 		FORMAT_NAME,
290 		ALGORITHM_NAME,
291 		BENCHMARK_COMMENT,
292 		BENCHMARK_LENGTH,
293 		0,
294 		PLAINTEXT_LENGTH,
295 		BINARY_SIZE,
296 		BINARY_ALIGN,
297 		SALT_SIZE,
298 		SALT_ALIGN,
299 		MIN_KEYS_PER_CRYPT,
300 		MAX_KEYS_PER_CRYPT,
301 		FMT_CASE | FMT_8_BIT | FMT_OMP,
302 		{ NULL },
303 		{ FORMAT_TAG },
304 		tests
305 	}, {
306 		init,
307 		done,
308 		fmt_default_reset,
309 		fmt_default_prepare,
310 		valid,
311 		fmt_default_split,
312 		get_binary,
313 		get_salt,
314 		{ NULL },
315 		fmt_default_source,
316 		{
317 			fmt_default_binary_hash_0,
318 			fmt_default_binary_hash_1,
319 			fmt_default_binary_hash_2,
320 			fmt_default_binary_hash_3,
321 			fmt_default_binary_hash_4,
322 			fmt_default_binary_hash_5,
323 			fmt_default_binary_hash_6
324 		},
325 		fmt_default_salt_hash,
326 		NULL,
327 		set_salt,
328 		set_key,
329 		get_key,
330 		fmt_default_clear_keys,
331 		crypt_all,
332 		{
333 #define COMMON_GET_HASH_LINK
334 #include "common-get-hash.h"
335 		},
336 		cmp_all,
337 		cmp_one,
338 		cmp_exact
339 	}
340 };
341 
342 #endif /* plugin stanza */
343