1 /*
2  * Common code for the Ansible Vault format.
3  */
4 
5 #include "arch.h"
6 #include "misc.h"
7 #include "common.h"
8 #include "ansible_common.h"
9 
10 struct fmt_tests ansible_tests[] = {
11 	{"$ansible$0*0*f623a48ba49f7abf7c1920bc1e2ab2607cda2b5786da2560b8178a6095e5dfd2*ab55de42e4f131f109f1a086f2e8e22f*6767c60857ce1d7aa20226d76ec1abf77837c623bb7e879147ab888ef15a0dbb", "openwall"},
12 	{"$ansible$0*0*45252709c61203511abbfdab0a8b498cb3e6259be5211e5b33ccc2fe12211d3f*0c52b98fc5aed891f99e3bcd3c6f250a*8e2d7558cd75b293ad8f3e27b774704279c019d89ba4743b591a3b14883c0851", "åbc"},
13 	{NULL}
14 };
15 
ansible_common_valid(char * ciphertext,struct fmt_main * self)16 int ansible_common_valid(char *ciphertext, struct fmt_main *self)
17 {
18 	char *ctcopy, *keeptr, *p;
19 	int value, extra;
20 
21 	if (strncmp(ciphertext, FORMAT_TAG, TAG_LENGTH) != 0)
22 		return 0;
23 
24 	ctcopy = strdup(ciphertext);
25 	keeptr = ctcopy;
26 
27 	ctcopy += TAG_LENGTH;
28 	if ((p = strtokm(ctcopy, "*")) == NULL) // version, for future purposes
29 		goto err;
30 	if (!isdec(p))
31 		goto err;
32 	value = atoi(p);
33 	if (value != 0)
34 		goto err;
35 	if ((p = strtokm(NULL, "*")) == NULL)   // cipher (fixed for now)
36 		goto err;
37 	if (!isdec(p))
38 		goto err;
39 	if (atoi(p) != 0)
40 		goto err;
41 	if ((p = strtokm(NULL, "*")) == NULL)   // salt
42 		goto err;
43 	if (hexlenl(p, &extra) != SALTLEN * 2 || extra)
44 		goto err;
45 	if ((p = strtokm(NULL, "*")) == NULL)   // ciphertext
46 		goto err;
47 	if (hexlenl(p, &extra) >= BLOBLEN * 2 || extra)
48 		goto err;
49 	if ((p = strtokm(NULL, "*")) == NULL)   // checksum
50 		goto err;
51 	if (hexlenl(p, &extra) != 32 * 2 || extra)
52 		goto err;
53 
54 	MEM_FREE(keeptr);
55 	return 1;
56 
57 err:
58 	MEM_FREE(keeptr);
59 	return 0;
60 }
61 
ansible_common_get_salt(char * ciphertext)62 void *ansible_common_get_salt(char *ciphertext)
63 {
64 	char *ctcopy = strdup(ciphertext);
65 	char *keeptr = ctcopy;
66 	int i;
67 	char *p;
68 	static struct custom_salt *cs;
69 
70 	cs = mem_calloc_tiny(sizeof(struct custom_salt), sizeof(uint64_t));
71 
72 	ctcopy += TAG_LENGTH;
73 	p = strtokm(ctcopy, "*");
74 	p = strtokm(NULL, "*");
75 	cs->iterations = 10000;  // fixed
76 	cs->salt_length = SALTLEN;
77 	p = strtokm(NULL, "*");
78 	for (i = 0; i < cs->salt_length; i++)
79 		cs->salt[i] = atoi16[ARCH_INDEX(p[i * 2])] * 16
80 			+ atoi16[ARCH_INDEX(p[i * 2 + 1])];
81 	p = strtokm(NULL, "*");
82 	cs->bloblen = strlen(p) / 2;
83 	for (i = 0; i < cs->bloblen; i++)
84 		cs->blob[i] = atoi16[ARCH_INDEX(p[i * 2])] * 16
85 			+ atoi16[ARCH_INDEX(p[i * 2 + 1])];
86 	p = strtokm(NULL, "*");
87 	for (i = 0; i < 32; i++)
88 		cs->checksum[i] = atoi16[ARCH_INDEX(p[i * 2])] * 16
89 			+ atoi16[ARCH_INDEX(p[i * 2 + 1])];
90 	MEM_FREE(keeptr);
91 
92 	return (void *)cs;
93 }
94 
ansible_common_get_binary(char * ciphertext)95 void *ansible_common_get_binary(char *ciphertext)
96 {
97 	static union {
98 		unsigned char c[BINARY_SIZE];
99 		uint32_t dummy;
100 	} buf;
101 	unsigned char *out = buf.c;
102 	char *p;
103 	int i;
104 
105 	memset(buf.c, 0, BINARY_SIZE);
106 	p = strrchr(ciphertext, '*') + 1;
107 	for (i = 0; i < BINARY_SIZE_CMP; i++) {
108 		out[i] = (atoi16[ARCH_INDEX(*p)] << 4) | atoi16[ARCH_INDEX(p[1])];
109 		p += 2;
110 	}
111 
112 	return out;
113 }
114 
ansible_common_iteration_count(void * salt)115 unsigned int ansible_common_iteration_count(void *salt)
116 {
117 	struct custom_salt *cs = salt;
118 
119 	return (unsigned int) cs->iterations;
120 }
121