1 /*
2  * This software is Copyright (c) 2016 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 <stdlib.h>
10 
11 #include "../mask_ext.h"
12 
13 #include "jtr_mask.h"
14 #include "pkt_comm/word_gen.h"
15 
16 /*
17  * Word generator configuration - used by devices
18  */
19 struct word_gen word_gen;
20 
21 
22 /*
23 static int static_gpu_locations[MASK_FMT_INT_PLHDR];
24 
25 	// Got the following code from some opencl_* implementations.
26 	// Could not discover when any of static_gpu_locations are other than -1.
27 	// Some opencl_* implementation operate without static_gpu_locations.
28 	//
29 	int i;
30 	for (i = 0; i < MASK_FMT_INT_PLHDR; i++)
31 		if (mask_skip_ranges && mask_skip_ranges[i] != -1)
32 			static_gpu_locations[i] = mask_int_cand.int_cpu_mask_ctx->
33 				ranges[mask_skip_ranges[i]].pos;
34 		else
35 			static_gpu_locations[i] = -1;
36 
37 	for (i = 0; i < MASK_FMT_INT_PLHDR; i++)
38 		if (static_gpu_locations[i] != -1) {
39 			fprintf(stderr,"!=> Unexpected mask data: static_gpu_locations: ");
40 			int j;
41 			for (j = 0; j < MASK_FMT_INT_PLHDR; j++)
42 				fprintf(stderr,"%d ", static_gpu_locations[j]);
43 			fprintf(stderr,"\n");
44 			break;
45 		}
46 */
47 
48 
mask_print()49 void mask_print()
50 {
51 	fprintf(stderr, "==========\n> num_int_cand:%d static:%d\n",
52 			mask_int_cand.num_int_cand, mask_gpu_is_static);
53 
54 	mask_cpu_context *mask = mask_int_cand.int_cpu_mask_ctx;
55 	fprintf(stderr, "> ps1:%d count:%d cpu_count:%d offset:%d\n",
56 			mask->ps1, mask->count, mask->cpu_count, mask->offset);
57 
58 	int i;
59 	for (i = 0; i < MAX_NUM_MASK_PLHDR; i++) {
60 		mask_range *range = mask->ranges + i;
61 		if (!range->count)
62 			break;
63 		fprintf(stderr, "> Range %d: count %d, pos %d, offset %d\n",
64 				i, range->count, range->pos, range->offset);
65 	}
66 
67 	for (i = 0; i < MASK_FMT_INT_PLHDR; i++) {
68 		if (mask_skip_ranges[i] == -1)
69 			continue;
70 		mask_range *range = mask_int_cand.int_cpu_mask_ctx->ranges
71 				+ mask_skip_ranges[i];
72 		fprintf(stderr, "i:%d\tskip_ranges[i]:%d\toff:%d\tpos:%d\n",
73 				i,mask_skip_ranges[i], range->offset, range->pos);
74 	}
75 }
76 
77 
mask_set_range_info(unsigned char * range_info)78 void mask_set_range_info(unsigned char *range_info)
79 {
80 	// In mask_mode, it inserts placeholders into the key.
81 	// Such as if the key is 'pwd', mask is '?d?w?d?d' then
82 	// set_key() gets '#pwd##' as an argument ('#' signs used).
83 	// Some mask data, such as int_cpu_mask_ctx->ranges[i].offset
84 	// is updated at every set_key() invocation.
85 	//
86 	// *-opencl implementations grab mask data and adds 4 bytes
87 	// of data (MASK_FMT_INT_PLHDR is 4) to every key.
88 	// Example follows.
89 	//
90 	//	int i;
91 	//	saved_int_key_loc[index] = 0;
92 	//	for (i = 0; i < MASK_FMT_INT_PLHDR; i++) {
93 	//		if (mask_skip_ranges[i] != -1)  {
94 	//			saved_int_key_loc[index] |= ((mask_int_cand.
95 	//			int_cpu_mask_ctx->ranges[mask_skip_ranges[i]].offset +
96 	//			mask_int_cand.int_cpu_mask_ctx->
97 	//			ranges[mask_skip_ranges[i]].pos) & 0xff) << (i << 3);
98 	//		}
99 	//		else
100 	//			saved_int_key_loc[index] |= 0x80 << (i << 3);
101 	//	}
102 
103 	// OK. Devices with pkt_comm_v2 use same approach.
104 	//
105 	int i;
106 	for (i = 0; i < MASK_FMT_INT_PLHDR; i++) {
107 		int range_num = mask_skip_ranges[i];
108 		if (range_num == -1)
109 			break;
110 
111 		// This range isn't unrolled on CPU, template key contains '#'
112 		mask_range *range = mask_int_cand.int_cpu_mask_ctx->ranges + range_num;
113 
114 		// Device takes new position for the range.
115 		// That shouldn't be less than range's original position.
116 		// If 2+ ranges are moved to the same position
117 		// (shouldn't happen) then the result is undefined.
118 		int new_pos = range->pos + range->offset;
119 		if (new_pos > 0x7f) {
120 			fprintf(stderr, "Error: Mask placeholder in position %d\n",
121 					new_pos);
122 			error();
123 		}
124 
125 		// Bit 7 indicates range is active.
126 		range_info[i] = 0x80 | new_pos;
127 	}
128 
129 	// If less than MASK_FMT_INT_PLHDR ranges are active
130 	// then range_info bytes are terminated with '\0'.
131 	if (i < MASK_FMT_INT_PLHDR)
132 		range_info[i] = 0;
133 }
134 
135 
136 // Creates configuration for on-board word generator
137 // using mask data
mask_convert_to_word_gen()138 struct word_gen *mask_convert_to_word_gen()
139 {
140 	if (mask_is_inactive())
141 		return &word_gen_words_pass_by;
142 
143 	int dst_range_num = 0;
144 	int i;
145 	for (i = 0; i < MASK_FMT_INT_PLHDR; i++) {
146 		int range_num = mask_skip_ranges[i];
147 		if (range_num == -1)
148 			break;
149 
150 		mask_range *range = mask_int_cand.int_cpu_mask_ctx->ranges + range_num;
151 		word_gen.ranges[dst_range_num].num_chars = range->count;
152 		word_gen.ranges[dst_range_num].start_idx = 0;
153 		memcpy(word_gen.ranges[dst_range_num].chars,
154 				range->chars, range->count);
155 		dst_range_num++;
156 	}
157 
158 	if (!dst_range_num) {
159 		fprintf(stderr, "mask_convert_to_word_gen: failed\n");
160 		exit(-1);
161 	}
162 
163 	word_gen.num_ranges = dst_range_num;
164 
165 	return &word_gen;
166 }
167 
168 // Reconstructs plaintext out of template key, range_info and
169 // ID of generated candidate.
170 // Assuming global mask didn't change since that.
171 // Designed for use in get_key(). 'key' is modified in place.
172 // If mask is not used or was deinitialized, then 'key'
173 // is not modified.
174 //
175 // This must be a good alternative to bitmap-like implementation,
176 // providing reasonable memory-to-CPU tradeoff.
177 //
mask_reconstruct_plaintext(char * key,unsigned char * range_info,unsigned int gen_id)178 void mask_reconstruct_plaintext(
179 		char *key,
180 		unsigned char *range_info,
181 		unsigned int gen_id)
182 {
183 	if (mask_is_inactive() || !mask_skip_ranges)
184 		return;
185 
186 	unsigned int total_count = gen_id;
187 	int i;
188 	for (i = MASK_FMT_INT_PLHDR - 1; i >= 0; i--) {
189 		int range_num = mask_skip_ranges[i];
190 		if (range_num == -1)
191 			continue;
192 
193 		mask_range *range = mask_int_cand.int_cpu_mask_ctx->ranges + range_num;
194 		int char_index = total_count % range->count;
195 		total_count /= range->count;
196 
197 		if (!range_info[i]) {
198 			// This shouldn't happen
199 			fprintf(stderr, "mask_reconstruct_plaintext: inconsistent data,"
200 					" key: '%s', gen_id=%d\n", key, gen_id);
201 			mask_print();
202 			break;
203 		}
204 		unsigned char new_pos = range_info[i] & 0x7f;
205 		key[new_pos] = range->chars[char_index];
206 	}
207 }
208