1 /*
2  * This software is Copyright (c) 2016-2017 Denis Burykin
3  * [denis_burykin yahoo com], [denis-burykin2014 yandex ru]
4  * and it is hereby released to the general public under the following terms:
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted.
7  *
8  */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/time.h>
13 #include <errno.h>
14 
15 #include "../../formats.h"
16 #include "../../loader.h"
17 
18 #include "../device_bitstream.h"
19 #include "pkt_comm.h"
20 #include "cmp_config.h"
21 
22 //
23 // Expecting salt and binaries are stored in network byte order
24 //
25 // Warning: global cmp_config
26 //
27 extern struct fmt_params *jtr_fmt_params;
28 
29 extern struct device_bitstream *jtr_bitstream;
30 
31 struct cmp_config cmp_config = {
32 	-1 // using sequential_id's that start from 0
33 };
34 
35 
memcmp_reverse(const void * a,const void * b,size_t n)36 static int memcmp_reverse(const void *a, const void *b, size_t n)
37 {
38 	if (!n)
39 		return 0;
40 
41 	const unsigned char *a_ptr = (const unsigned char *)a + n - 1;
42 	const unsigned char *b_ptr = (const unsigned char *)b + n - 1;
43 
44 	while (n > 0) {
45 		if (*a_ptr != *b_ptr)
46 			return *a_ptr - *b_ptr;
47 		a_ptr--;
48 		b_ptr--;
49 		n--;
50 	}
51 	return 0;
52 }
53 
compare_binaries(const void * a,const void * b)54 static int compare_binaries(const void *a, const void *b)
55 {
56 	return memcmp_reverse(
57 		(*(struct db_password **)a)->binary,
58 		(*(struct db_password **)b)->binary,
59 		jtr_fmt_params->binary_size);
60 }
61 
62 
63 // Create 'struct cmp_config' w/o comparator data (no hashes sent from host)
cmp_config_nocompar_new(struct db_salt * salt,void * salt_ptr,int salt_len)64 void cmp_config_nocompar_new(struct db_salt *salt, void *salt_ptr, int salt_len)
65 {
66 	cmp_config.id = salt->sequential_id;
67 
68 	int cost_num;
69 	for (cost_num = 0; cost_num < FMT_TUNABLE_COSTS; cost_num ++) {
70 		if (jtr_fmt_params->tunable_cost_name[cost_num])
71 			cmp_config.tunable_costs[cost_num] = salt->cost[cost_num];
72 		else
73 			cmp_config.tunable_costs[cost_num] = 0;
74 	}
75 
76 	cmp_config.salt_ptr = salt_ptr;
77 	cmp_config.salt_len = salt_len;
78 
79 	cmp_config.num_hashes = 0;
80 }
81 
82 
83 //struct cmp_config *
cmp_config_new(struct db_salt * salt,void * salt_ptr,int salt_len)84 void cmp_config_new(struct db_salt *salt, void *salt_ptr, int salt_len)
85 {
86 	//struct cmp_config *cmp_config = malloc(sizeof(struct cmp_config));
87 	//if (!cmp_config) {
88 	//	fprintf(stderr, "cmp_config_new: malloc()\n");
89 	//	exit(-1);
90 	//}
91 	static int warning_num_hashes = 0;
92 	int num_hashes = salt->count;
93 	if (num_hashes > jtr_bitstream->cmp_entries_max) {
94 		num_hashes = jtr_bitstream->cmp_entries_max;
95 		if (!warning_num_hashes) {
96 			fprintf(stderr, "Warning: salt with %d hashes, device supports "
97 				"max. %d hashes/salt, extra hashes ignored\n",
98 				salt->count, jtr_bitstream->cmp_entries_max);
99 			warning_num_hashes = 1;
100 		}
101 	}
102 
103 	if (!num_hashes) {
104 		fprintf(stderr, "cmp_config_new: num_hashes == 0\n");
105 		exit(-1);
106 	}
107 
108 	if (!cmp_config.pw || cmp_config.num_hashes_max < num_hashes) {
109 		if (cmp_config.pw)
110 			free(cmp_config.pw);
111 
112 		int size = num_hashes * sizeof(struct db_password *);
113 		cmp_config.pw = malloc(size);
114 		if (!cmp_config.pw) {
115 			fprintf(stderr, "cmp_config_new: malloc(%d) failed\n", size);
116 			exit(-1);
117 		}
118 		cmp_config.num_hashes_max = num_hashes;
119 	}
120 
121 	cmp_config.id = salt->sequential_id;
122 
123 	int cost_num;
124 	for (cost_num = 0; cost_num < FMT_TUNABLE_COSTS; cost_num ++) {
125 		if (jtr_fmt_params->tunable_cost_name[cost_num])
126 			cmp_config.tunable_costs[cost_num] = salt->cost[cost_num];
127 		else
128 			cmp_config.tunable_costs[cost_num] = 0;
129 	}
130 
131 	// db_salt->salt depends on host system (e.g. different on 32 and 64-bit).
132 	// salt length may also vary.
133 	// Format has to provide binary salt in arch-independent form,
134 	// typically network-byte order, and provide correct salt_len.
135 	//cmp_config.salt = salt->salt;
136 	cmp_config.salt_ptr = salt_ptr;
137 	cmp_config.salt_len = salt_len;
138 
139 	cmp_config.num_hashes = 0;
140 
141 	int offset = 0;
142 	struct db_password *pw;
143 	for (pw = salt->list; pw; pw = pw->next) {
144 		// FMT_REMOVE issue.
145 		// pw->binary is excluded from the list and(or) NULL'ed
146 		// on any successful guess, regardless of FMT_REMOVE flag.
147 		if (!pw->binary)
148 			continue;
149 		cmp_config.pw[offset++] = pw;
150 		cmp_config.num_hashes ++;
151 		if (cmp_config.num_hashes == jtr_bitstream->cmp_entries_max)
152 			break;
153 	}
154 
155 	if (cmp_config.num_hashes == 1)
156 		return;
157 
158 	// sort hashes in ascending order
159 	qsort(cmp_config.pw, cmp_config.num_hashes,
160 			sizeof(struct db_password *), compare_binaries);
161 }
162 
163 
pkt_cmp_config_new(struct cmp_config * cmp_config)164 struct pkt *pkt_cmp_config_new(struct cmp_config *cmp_config)
165 {
166 	int binary_size = jtr_fmt_params->binary_size;
167 
168 	int size = 3 + cmp_config->salt_len
169 			+ cmp_config->num_hashes * binary_size
170 			+ 4 * FMT_TUNABLE_COSTS;
171 	char *data = malloc(size);
172 	if (!data) {
173 		pkt_error("pkt_cmp_config_new(): unable to allocate %d bytes\n",
174 				size);
175 		return NULL;
176 	}
177 
178 	int offset = 0;
179 
180 	// PKT_TYPE_CMP_CONFIG. Salt starts at offset 0.
181 	memcpy(data + offset, cmp_config->salt_ptr, cmp_config->salt_len);
182 	offset += cmp_config->salt_len;
183 #if 0
184 	if (cmp_config->num_hashes > jtr_bitstream->cmp_entries_max
185 			|| !cmp_config->num_hashes) {
186 		pkt_error("pkt_cmp_config_new(): bad num_hashes=%d\n",
187 				cmp_config->num_hashes);
188 		return NULL;
189 	}
190 #endif
191 	// If format has tunable costs - send after salt
192 	// (4 bytes each tunable cost value)
193 	int tunable_cost_num;
194 	for (tunable_cost_num = 0; tunable_cost_num < FMT_TUNABLE_COSTS;
195 				tunable_cost_num ++) {
196 		unsigned int cost = cmp_config->tunable_costs[tunable_cost_num];
197 		if (!cost)
198 			break;
199 
200 		data[offset++] = cost;
201 		data[offset++] = cost >> 8;
202 		data[offset++] = cost >> 16;
203 		data[offset++] = cost >> 24;
204 	}
205 
206 	// PKT_TYPE_CMP_CONFIG. After salt - num_hashes (2 bytes).
207 	data[offset++] = cmp_config->num_hashes;
208 	data[offset++] = cmp_config->num_hashes >> 8;
209 
210 	// PKT_TYPE_CMP_CONFIG. After num_hashes - sorted binaries.
211 	int i;
212 	for (i = 0; i < cmp_config->num_hashes; i++) {
213 		memcpy(data + offset, cmp_config->pw[i]->binary, binary_size);
214 		offset += binary_size;
215 	}
216 
217 	// PKT_TYPE_CMP_CONFIG. 0xCC is the last byte in the packet.
218 	data[offset++] = 0xCC;
219 
220 	struct pkt *pkt = pkt_new(PKT_TYPE_CMP_CONFIG, data, offset);
221 	/*
222 	for (i=0; i < offset; i++) {
223 		if ( !((i-4)%5) )
224 			printf("\n");
225 		printf("0x%02x ", data[i] & 0xff);
226 	}
227 	printf("data_len: %d\n", offset);
228 	*/
229 	return pkt;
230 }
231 
232