1 /*
2  * GOST 3411 cracker patch for JtR. Hacked together during
3  * May of 2012 by Dhiru Kholia <dhiru.kholia at gmail.com>,
4  * Sergey V. <sftp.mtuci at gmail com>, and JimF
5  *
6  * This software is Copyright (c) 2012, Dhiru Kholia <dhiru.kholia at gmail.com>,
7  * Sergey V. <sftp.mtuci at gmail com>, and JimF
8  * and it is hereby released to the general public under the following terms:
9  * Redistribution and use in source and binary forms, with or without modification,
10  * are permitted.
11  *
12  * Input Format => user:gost-hash;
13  *		   user:$gost$gost-hash;
14  *		   user:$gost-cp$gost-cryptopro-hash;
15  */
16 
17 #if FMT_EXTERNS_H
18 extern struct fmt_main fmt_gost;
19 #elif FMT_REGISTERS_H
20 john_register_one(&fmt_gost);
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 "common.h"
32 #include "formats.h"
33 #include "params.h"
34 #include "options.h"
35 #include "gost.h"
36 
37 #define FORMAT_LABEL            "gost"
38 #define FORMAT_NAME             "GOST R 34.11-94"
39 
40 #define FORMAT_TAG              "$gost$"
41 #define TAG_LENGTH              (sizeof(FORMAT_TAG)-1)
42 #define FORMAT_TAG_CP           "$gost-cp$"
43 #define TAG_CP_LENGTH           (sizeof(FORMAT_TAG_CP)-1)
44 #if !defined(USE_GCC_ASM_IA32) && defined(USE_GCC_ASM_X64)
45 #define ALGORITHM_NAME          "64/64"
46 #else
47 #define ALGORITHM_NAME          "32/" ARCH_BITS_STR
48 #endif
49 #define BENCHMARK_COMMENT       ""
50 #define BENCHMARK_LENGTH        0x507 // Actually unsalted but two variants
51 #define PLAINTEXT_LENGTH        125
52 #define CIPHERTEXT_LENGTH       64
53 #define BINARY_SIZE             32
54 #define SALT_SIZE               1
55 #define SALT_ALIGN              1
56 #define BINARY_ALIGN            sizeof(uint32_t)
57 #define MIN_KEYS_PER_CRYPT      1
58 #define MAX_KEYS_PER_CRYPT      128
59 
60 #ifndef OMP_SCALE
61 #define OMP_SCALE               2 // Tuned w/ MKPC for core i7
62 #endif
63 
64 static struct fmt_tests gost_tests[] = {
65 	{"ce85b99cc46752fffee35cab9a7b0278abb4c2d2055cff685af4912c49490f8d", ""},
66 	{"d42c539e367c66e9c88a801f6649349c21871b4344c6a573f849fdce62f314dd", "a"},
67 	{FORMAT_TAG    "ce85b99cc46752fffee35cab9a7b0278abb4c2d2055cff685af4912c49490f8d", ""},
68 	{FORMAT_TAG    "d42c539e367c66e9c88a801f6649349c21871b4344c6a573f849fdce62f314dd", "a"},
69 	{FORMAT_TAG    "ad4434ecb18f2c99b60cbe59ec3d2469582b65273f48de72db2fde16a4889a4d", "message digest"},
70 	{FORMAT_TAG    "0886f91e7fcaff65eb2635a1a4c9f203003e0ce5ea74b72fc6462cc72649694e",
71 	 "This is very very long pass phrase for test gost hash function."},
72 	{FORMAT_TAG_CP "981e5f3ca30c841487830f84fb433e13ac1101569b9c13584ac483234cd656c0", ""},
73 	{FORMAT_TAG_CP "e74c52dd282183bf37af0079c9f78055715a103f17e3133ceff1aacf2f403011", "a"},
74 	{FORMAT_TAG_CP "bc6041dd2aa401ebfa6e9886734174febdb4729aa972d60f549ac39b29721ba0", "message digest"},
75 	{FORMAT_TAG_CP "5394adfacb65a9ac5781c3080b244c955a9bf03befd51582c3850b8935f80762",
76 	 "This is very very long pass phrase for test gost hash function."},
77 	{NULL}
78 };
79 
80 static char (*saved_key)[PLAINTEXT_LENGTH + 1];
81 static uint32_t (*crypt_out)[8];
82 static int is_cryptopro; /* non 0 for CryptoPro hashes */
83 
init(struct fmt_main * self)84 static void init(struct fmt_main *self)
85 {
86 	omp_autotune(self, OMP_SCALE);
87 
88 	gost_init_table();
89 	saved_key = mem_calloc(self->params.max_keys_per_crypt,
90 	                       sizeof(*saved_key));
91 	crypt_out = mem_calloc(self->params.max_keys_per_crypt,
92 	                       sizeof(*crypt_out));
93 }
94 
done(void)95 static void done(void)
96 {
97 	MEM_FREE(crypt_out);
98 	MEM_FREE(saved_key);
99 }
100 
valid(char * ciphertext,struct fmt_main * self)101 static int valid(char *ciphertext, struct fmt_main *self)
102 {
103 	char *p, *q;
104 
105 	p = ciphertext;
106 
107 	if (!strncmp(p, FORMAT_TAG, TAG_LENGTH))
108 		p += TAG_LENGTH;
109 	else if (!strncmp(p, FORMAT_TAG_CP, TAG_CP_LENGTH))
110 		p += TAG_CP_LENGTH;
111 
112 	q = p;
113 	while (atoi16[ARCH_INDEX(*q)] != 0x7F)
114 		q++;
115 
116 	return !*q && q - p == CIPHERTEXT_LENGTH;
117 }
118 
119 
split(char * ciphertext,int index,struct fmt_main * self)120 static char *split(char *ciphertext, int index, struct fmt_main *self)
121 {
122 	static char out[TAG_CP_LENGTH + CIPHERTEXT_LENGTH + 1];
123 	char *cp=&out[TAG_LENGTH];
124 	strcpy(out, FORMAT_TAG);
125 	if (!strncmp(ciphertext, FORMAT_TAG, TAG_LENGTH))
126 		ciphertext += TAG_LENGTH;
127 	else if (!strncmp(ciphertext, FORMAT_TAG_CP, TAG_CP_LENGTH)) {
128 		ciphertext += TAG_CP_LENGTH;
129 		strcpy(out, FORMAT_TAG_CP);
130 		cp=&out[TAG_CP_LENGTH];
131 	}
132 	memcpy(cp, ciphertext, CIPHERTEXT_LENGTH + 1);
133 	strlwr(cp);
134 	return out;
135 }
136 
get_salt(char * ciphertext)137 static void *get_salt(char *ciphertext)
138 {
139 	static char i;
140 
141 	if (!strncmp(ciphertext, FORMAT_TAG, TAG_LENGTH))
142 		i=0;
143 	else
144 		i=1;
145 	return &i;
146 }
147 
set_salt(void * salt)148 static void set_salt(void *salt)
149 {
150 	is_cryptopro = *(char*)salt;
151 }
152 
get_binary(char * ciphertext)153 static void *get_binary(char *ciphertext)
154 {
155 	static unsigned char *out;
156 	char *p;
157 	int i;
158 
159 	if (!out) out = mem_alloc_tiny(BINARY_SIZE, MEM_ALIGN_WORD);
160 
161 	if (!strncmp(ciphertext, FORMAT_TAG, TAG_LENGTH))
162 		p = ciphertext + TAG_LENGTH;
163 	else
164 		p = ciphertext + TAG_CP_LENGTH;
165 
166 	for (i = 0; i < BINARY_SIZE; i++) {
167 		out[i] =
168 		    (atoi16[ARCH_INDEX(*p)] << 4) |
169 		    atoi16[ARCH_INDEX(p[1])];
170 		p += 2;
171 	}
172 
173 	return out;
174 }
175 
176 #define COMMON_GET_HASH_VAR crypt_out
177 #include "common-get-hash.h"
178 
crypt_all(int * pcount,struct db_salt * salt)179 static int crypt_all(int *pcount, struct db_salt *salt)
180 {
181 	const int count = *pcount;
182 	int index;
183 #ifdef _OPENMP
184 #pragma omp parallel for
185 #endif
186 	for (index = 0; index < count; index++) {
187 		gost_ctx ctx;
188 
189 		if (is_cryptopro)
190 			john_gost_cryptopro_init(&ctx);
191 		else
192 			john_gost_init(&ctx);
193 		john_gost_update(&ctx, (const unsigned char*)saved_key[index],
194 			    strlen(saved_key[index]));
195 
196 		john_gost_final(&ctx, (unsigned char *)crypt_out[index]);
197 	}
198 
199 	return count;
200 }
201 
cmp_all(void * binary,int count)202 static int cmp_all(void *binary, int count)
203 {
204 	int index;
205 
206 	for (index = 0; index < count; index++)
207 		if (crypt_out[index][0] == *(uint32_t*)binary)
208 			return 1;
209 
210 	return 0;
211 }
212 
cmp_one(void * binary,int index)213 static int cmp_one(void *binary, int index)
214 {
215 	return !memcmp(binary, crypt_out[index], BINARY_SIZE);
216 }
217 
cmp_exact(char * source,int index)218 static int cmp_exact(char *source, int index)
219 {
220 	return 1;
221 }
222 
set_key(char * key,int index)223 static void set_key(char *key, int index)
224 {
225 	strnzcpy(saved_key[index], key, sizeof(*saved_key));
226 }
227 
get_key(int index)228 static char *get_key(int index)
229 {
230 	return saved_key[index];
231 }
232 
233 struct fmt_main fmt_gost = {
234 	{
235 		FORMAT_LABEL,
236 		FORMAT_NAME,
237 		ALGORITHM_NAME,
238 		BENCHMARK_COMMENT,
239 		BENCHMARK_LENGTH,
240 		0,
241 		PLAINTEXT_LENGTH,
242 		BINARY_SIZE,
243 		BINARY_ALIGN,
244 		SALT_SIZE,
245 		SALT_ALIGN,
246 		MIN_KEYS_PER_CRYPT,
247 		MAX_KEYS_PER_CRYPT,
248 		FMT_CASE | FMT_8_BIT | FMT_OMP | FMT_SPLIT_UNIFIES_CASE,
249 		{ NULL },
250 		{ FORMAT_TAG, FORMAT_TAG_CP },
251 		gost_tests
252 	}, {
253 		init,
254 		done,
255 		fmt_default_reset,
256 		fmt_default_prepare,
257 		valid,
258 		split,
259 		get_binary,
260 		get_salt,
261 		{ NULL },
262 		fmt_default_source,
263 		{
264 			fmt_default_binary_hash_0,
265 			fmt_default_binary_hash_1,
266 			fmt_default_binary_hash_2,
267 			fmt_default_binary_hash_3,
268 			fmt_default_binary_hash_4,
269 			fmt_default_binary_hash_5,
270 			fmt_default_binary_hash_6
271 		},
272 		fmt_default_salt_hash,
273 		NULL,
274 		set_salt,
275 		set_key,
276 		get_key,
277 		fmt_default_clear_keys,
278 		crypt_all,
279 		{
280 #define COMMON_GET_HASH_LINK
281 #include "common-get-hash.h"
282 		},
283 		cmp_all,
284 		cmp_one,
285 		cmp_exact
286 	}
287 };
288 
289 #endif /* plugin stanza */
290