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