1 /*
2  * Office 2007 cracker patch for JtR. Hacked together during March of 2012 by
3  * Dhiru Kholia <dhiru.kholia at gmail.com>.
4  */
5 
6 #if FMT_EXTERNS_H
7 extern struct fmt_main fmt_office;
8 #elif FMT_REGISTERS_H
9 john_register_one(&fmt_office);
10 #else
11 
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 
16 #ifdef _OPENMP
17 #include <omp.h>
18 #endif
19 
20 #include "arch.h"
21 #include "misc.h"
22 #include "common.h"
23 #include "formats.h"
24 #include "params.h"
25 #include "options.h"
26 #include "unicode.h"
27 #include "aes.h"
28 #include "sha.h"
29 #include "sha2.h"
30 #include "johnswap.h"
31 #include "office_common.h"
32 #include "simd-intrinsics.h"
33 
34 #define FORMAT_LABEL             "Office"
35 #define FORMAT_NAME              "2007/2010/2013"
36 #define ALGORITHM_NAME           "SHA1 " SHA1_ALGORITHM_NAME " / SHA512 " SHA512_ALGORITHM_NAME " AES"
37 #define BENCHMARK_COMMENT        ""
38 #define BENCHMARK_LENGTH         0x107
39 #define PLAINTEXT_LENGTH         125
40 #define BINARY_SIZE              16
41 #define SALT_SIZE                sizeof(*cur_salt)
42 #define BINARY_ALIGN             4
43 #define SALT_ALIGN               sizeof(int)
44 #ifdef SIMD_COEF_32
45 #define GETPOS_512W(i, index)    ( (index&(SIMD_COEF_64-1))*8 + ((i*8)&(0xffffffff-7))*SIMD_COEF_64 + (unsigned int)index/SIMD_COEF_64*SHA_BUF_SIZ*SIMD_COEF_64*8 )
46 #define GETOUTPOS_512W(i, index) ( (index&(SIMD_COEF_64-1))*8 + ((i*8)&(0xffffffff-7))*SIMD_COEF_64 + (unsigned int)index/SIMD_COEF_64*8*SIMD_COEF_64*8 )
47 #if ARCH_LITTLE_ENDIAN==1
48 #define GETPOS_1(i, index)       ( (index&(SIMD_COEF_32-1))*4 + ((i)&(0xffffffff-3))*SIMD_COEF_32 + (3-((i)&3)) + (unsigned int)index/SIMD_COEF_32*SHA_BUF_SIZ*SIMD_COEF_32*4 )
49 #define GETPOS_512(i, index)     ( (index&(SIMD_COEF_64-1))*8 + ((i)&(0xffffffff-7))*SIMD_COEF_64 + (7-((i)&7)) + (unsigned int)index/SIMD_COEF_64*SHA_BUF_SIZ*SIMD_COEF_64*8 )
50 #define GETOUTPOS_512(i, index)  ( (index&(SIMD_COEF_64-1))*8 + ((i)&(0xffffffff-7))*SIMD_COEF_64 + (7-((i)&7)) + (unsigned int)index/SIMD_COEF_64*8*SIMD_COEF_64*8 )
51 #else
52 #define GETPOS_1(i, index)       ( (index&(SIMD_COEF_32-1))*4 + ((i)&(0xffffffff-3))*SIMD_COEF_32 + ((i)&3) + (unsigned int)index/SIMD_COEF_32*SHA_BUF_SIZ*SIMD_COEF_32*4 )
53 #define GETPOS_512(i, index)     ( (index&(SIMD_COEF_64-1))*8 + ((i)&(0xffffffff-7))*SIMD_COEF_64 + ((i)&7) + (unsigned int)index/SIMD_COEF_64*SHA_BUF_SIZ*SIMD_COEF_64*8 )
54 #define GETOUTPOS_512(i, index)  ( (index&(SIMD_COEF_64-1))*8 + ((i)&(0xffffffff-7))*SIMD_COEF_64 + ((i)&7) + (unsigned int)index/SIMD_COEF_64*8*SIMD_COEF_64*8 )
55 #endif
56 #define SHA1_LOOP_CNT            (SIMD_COEF_32*SIMD_PARA_SHA1)
57 #define SHA512_LOOP_CNT          (SIMD_COEF_64 * SIMD_PARA_SHA512)
58 #define MIN_KEYS_PER_CRYPT       (SIMD_COEF_32 * SIMD_PARA_SHA1 * SIMD_PARA_SHA512)
59 #define MAX_KEYS_PER_CRYPT       (SIMD_COEF_32 * SIMD_PARA_SHA1 * SIMD_PARA_SHA512)
60 #else
61 #define SHA1_LOOP_CNT            1
62 #define SHA512_LOOP_CNT          1
63 #define MIN_KEYS_PER_CRYPT       1
64 #define MAX_KEYS_PER_CRYPT       1
65 #endif
66 
67 #ifndef OMP_SCALE
68 #define OMP_SCALE                1 // MKPC and scale tuned for i7
69 #endif
70 
71 static struct fmt_tests office_tests[] = {
72 	{"$office$*2007*20*128*16*8b2c9e8c878844fc842012273be4bea8*aa862168b80d8c45c852696a8bb499eb*a413507fabe2d87606595f987f679ff4b5b4c2cd", "Password"},
73 	/* 2007-Default_myhovercraftisfullofeels_.docx */
74 	{"$office$*2007*20*128*16*91f095a1fd02595359fe3938fa9236fd*e22668eb1347957987175079e980990f*659f50b9062d36999bf3d0911068c93268ae1d86", "myhovercraftisfullofeels"},
75 	/* 2007-Default_myhovercraftisfullofeels_.dotx */
76 	{"$office$*2007*20*128*16*56ea65016fbb4eac14a6770b2dbe7e99*8cf82ce1b62f01fd3b2c7666a2313302*21443fe938177e648c482da72212a8848c2e9c80", "myhovercraftisfullofeels"},
77 	/* 2007-Default_myhovercraftisfullofeels_.xlsb */
78 	{"$office$*2007*20*128*16*fbd4cc5dab9b8e341778ddcde9eca740*3a040a9cef3d3675009b22f99718e39c*48053b27e95fa53b3597d48ca4ad41eec382e0c8", "myhovercraftisfullofeels"},
79 	/* 2007-Default_myhovercraftisfullofeels_.xlsm */
80 	{"$office$*2007*20*128*16*fbd4cc5dab9b8e341778ddcde9eca740*92bb2ef34ca662ca8a26c8e2105b05c0*0261ba08cd36a324aa1a70b3908a24e7b5a89dd6", "myhovercraftisfullofeels"},
81 	/* 2007-Default_myhovercraftisfullofeels_.xlsx */
82 	{"$office$*2007*20*128*16*fbd4cc5dab9b8e341778ddcde9eca740*46bef371486919d4bffe7280110f913d*b51af42e6696baa097a7109cebc3d0ff7cc8b1d8", "myhovercraftisfullofeels"},
83 	/* 2007-Default_myhovercraftisfullofeels_.xltx */
84 	{"$office$*2007*20*128*16*fbd4cc5dab9b8e341778ddcde9eca740*1addb6823689aca9ce400be8f9e55fc9*e06bf10aaf3a4049ffa49dd91cf9e7bbf88a1b3b", "myhovercraftisfullofeels"},
85 	/* 2010-Default_myhovercraftisfullofeels_.docx */
86 	{"$office$*2010*100000*128*16*213aefcafd9f9188e78c1936cbb05a44*d5fc7691292ab6daf7903b9a8f8c8441*46bfac7fb87cd43bd0ab54ebc21c120df5fab7e6f11375e79ee044e663641d5e", "myhovercraftisfullofeels"},
87 	/* 2010-Default_myhovercraftisfullofeels_.dotx */
88 	{"$office$*2010*100000*128*16*0907ec6ecf82ede273b7ee87e44f4ce5*d156501661638cfa3abdb7fdae05555e*4e4b64e12b23f44d9a8e2e00196e582b2da70e5e1ab4784384ad631000a5097a", "myhovercraftisfullofeels"},
89 	/* 2010-Default_myhovercraftisfullofeels_.xlsb */
90 	{"$office$*2010*100000*128*16*71093d08cf950f8e8397b8708de27c1f*00780eeb9605c7e27227c5619e91dc21*90aaf0ea5ccc508e699de7d62c310f94b6798ae77632be0fc1a0dc71600dac38", "myhovercraftisfullofeels"},
91 	/* 2010-Default_myhovercraftisfullofeels_.xlsx */
92 	{"$office$*2010*100000*128*16*71093d08cf950f8e8397b8708de27c1f*ef51883a775075f30d2207e87987e6a3*a867f87ea955d15d8cb08dc8980c04bf564f8af060ab61bf7fa3543853e0d11a", "myhovercraftisfullofeels"},
93 	/* 2013-openwall.pptx */
94 	{"$office$*2013*100000*256*16*9b12805dd6d56f46d07315153f3ecb9c*c5a4a167b51faa6629f6a4caf0b4baa8*87397e0659b2a6fff90291f8e6d6d0018b750b792fefed77001edbafba7769cd", "openwall"},
95 	/* 365-2013-openwall.docx */
96 	{"$office$*2013*100000*256*16*774a174239a7495a59cac39a122d991c*b2f9197840f9e5d013f95a3797708e83*ecfc6d24808691aac0daeaeba72aba314d72c6bbd12f7ff0ea1a33770187caef", "openwall"},
97 	/* 365-2013-password.docx */
98 	{"$office$*2013*100000*256*16*d4fc9302eedabf9872b24ca700a5258b*7c9554d582520747ec3e872f109a7026*1af5b5024f00e35eaf5fd8148b410b57e7451a32898acaf14275a8c119c3a4fd", "password"},
99 	/* 365-2013-password.xlsx */
100 	{"$office$*2013*100000*256*16*59b49c64c0d29de733f0025837327d50*70acc7946646ea300fc13cfe3bd751e2*627c8bdb7d9846228aaea81eeed434d022bb93bb5f4da146cb3ad9d847de9ec9", "password"},
101 	/* 365-2013-strict-password.docx */
102 	{"$office$*2013*100000*256*16*f1c23049d85876e6b20e95ab86a477f1*13303dbd27a38ea86ef11f1b2bc56225*9a69596de0655a6c6a5b2dc4b24d6e713e307fb70af2d6b67b566173e89f941d", "password"},
103 
104 	/* Max password length data, 125 bytes.  Made with pass_gen.pl */
105 	{"$office$*2007*20*128*16*7268323350556e527671367031526263*54344b786a6967615052493837496735*96c9d7cc44e81971aadfe81cce88cb8b00000000", "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345"},
106 	{"$office$*2010*100000*128*16*42624931633777446c67354e34686e64*73592fdc2ecb12cd8dcb3ca2cec852bd*82f7315701818a7150ed7a7977717d0b56dcd1bc27e40a23dee6287a6ed55f9b", "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345"},
107 	{"$office$*2013*100000*256*16*36537a3373756b587632386d77665362*c5958bd6177be548ce33d99f8e4fd7a7*43baa9dfab09a7e54b9d719dbe5187f1f7b55d7b761361fe1f60c85b044aa125", "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345"},
108 
109 	/* Office 2019 - sample Word document */
110 	{"$office$*2013*100000*256*16*f4984f25c246bb742259ec55b4bab10c*d7608a90d1f552b6910c5d4ab110e276*04a6a1549a25d4871f63d2d2aa098fd2d6c74ddefcdec92a9616fb48a583f259", "openwall"},
111 	{NULL}
112 };
113 
114 static ms_office_custom_salt *cur_salt;
115 
116 #define MS_OFFICE_2007_ITERATIONS	50000
117 
118 /* Password encoded in UCS-2 */
119 static UTF16 (*saved_key)[PLAINTEXT_LENGTH + 1];
120 /* UCS-2 password length, in octets */
121 static int *saved_len;
122 static uint32_t (*crypt_key)[4];
123 static int *cracked;
124 
125 /* Office 2010/2013 */
126 static const unsigned char encryptedVerifierHashInputBlockKey[] = { 0xfe, 0xa7, 0xd2, 0x76, 0x3b, 0x4b, 0x9e, 0x79 };
127 static const unsigned char encryptedVerifierHashValueBlockKey[] = { 0xd7, 0xaa, 0x0f, 0x6d, 0x30, 0x61, 0x34, 0x4e };
128 
DeriveKey(unsigned char * hashValue,unsigned char * X1)129 static unsigned char *DeriveKey(unsigned char *hashValue, unsigned char *X1)
130 {
131 	int i;
132 	unsigned char derivedKey[64];
133 	SHA_CTX ctx;
134 
135 	// This is step 4a in 2.3.4.7 of MS_OFFCRYPT version 1.0
136 	// and is required even though the notes say it should be
137 	// used only when the encryption algorithm key > hash length.
138 	for (i = 0; i < 64; i++)
139 		derivedKey[i] = (i < 20 ? 0x36 ^ hashValue[i] : 0x36);
140 
141 	SHA1_Init(&ctx);
142 	SHA1_Update(&ctx, derivedKey, 64);
143 	SHA1_Final(X1, &ctx);
144 
145 	if (cur_salt->verifierHashSize > cur_salt->keySize/8)
146 		return X1;
147 
148 	/* TODO: finish up this function */
149 	//for (i = 0; i < 64; i++)
150 	//	derivedKey[i] = (i < 30 ? 0x5C ^ hashValue[i] : 0x5C);
151 
152 	fprintf(stderr, "\n\n*** ERROR: DeriveKey() entered Limbo.\n");
153 	fprintf(stderr, "Please report to john-dev mailing list.\n");
154 	error();
155 
156 	return NULL;
157 }
158 
159 #ifdef SIMD_COEF_32
GeneratePasswordHashUsingSHA1(int idx,unsigned char final[SHA1_LOOP_CNT][20])160 static void GeneratePasswordHashUsingSHA1(int idx, unsigned char final[SHA1_LOOP_CNT][20])
161 {
162 	unsigned char hashBuf[20];
163 	/* H(0) = H(salt, password)
164 	 * hashBuf = SHA1Hash(salt, password);
165 	 * create input buffer for SHA1 from salt and unicode version of password */
166 	unsigned char X1[20];
167 	SHA_CTX ctx;
168 	unsigned char _IBuf[64*SHA1_LOOP_CNT+MEM_ALIGN_CACHE], *keys;
169 	uint32_t *keys32;
170 	unsigned i, j;
171 
172 	keys = (unsigned char*)mem_align(_IBuf, MEM_ALIGN_CACHE);
173 	keys32 = (uint32_t*)keys;
174 	memset(keys, 0, 64*SHA1_LOOP_CNT);
175 
176 	for (i = 0; i < SHA1_LOOP_CNT; ++i) {
177 		SHA1_Init(&ctx);
178 		SHA1_Update(&ctx, cur_salt->osalt, cur_salt->saltSize);
179 		SHA1_Update(&ctx, saved_key[idx+i], saved_len[idx+i]);
180 		SHA1_Final(hashBuf, &ctx);
181 
182 		/* Generate each hash in turn
183 		 * H(n) = H(i, H(n-1))
184 		 * hashBuf = SHA1Hash(i, hashBuf); */
185 
186 		// Create a byte array of the integer and put at the front of the input buffer
187 		// 1.3.6 says that little-endian byte ordering is expected
188 		for (j = 4; j < 24; ++j)
189 			keys[GETPOS_1(j, i)] = hashBuf[j-4];
190 		keys[GETPOS_1(j, i)] = 0x80;
191 		// 24 bytes of crypt data (192 bits).
192 		keys[GETPOS_1(63, i)] = 192;
193 	}
194 	// we do 1 less than actual number of iterations here.
195 	for (i = 0; i < MS_OFFICE_2007_ITERATIONS-1; i++) {
196 		for (j = 0; j < SHA1_LOOP_CNT; ++j) {
197 			keys[GETPOS_1(0, j)] = i&0xff;
198 			keys[GETPOS_1(1, j)] = i>>8;
199 		}
200 		// Here we output to 4 bytes past start of input buffer.
201 		SIMDSHA1body(keys, &keys32[SIMD_COEF_32], NULL, SSEi_MIXED_IN|SSEi_OUTPUT_AS_INP_FMT);
202 	}
203 	// last iteration is output to start of input buffer, then 32 bit 0 appended.
204 	// but this is still ends up being 24 bytes of crypt data.
205 	for (j = 0; j < SHA1_LOOP_CNT; ++j) {
206 		keys[GETPOS_1(0, j)] = i&0xff;
207 		keys[GETPOS_1(1, j)] = i>>8;
208 	}
209 	SIMDSHA1body(keys, keys32, NULL, SSEi_MIXED_IN|SSEi_OUTPUT_AS_INP_FMT);
210 
211 	// Finally, append "block" (0) to H(n)
212 	// hashBuf = SHA1Hash(hashBuf, 0);
213 	for (i = 0; i < SHA1_LOOP_CNT; ++i) {
214 		keys[GETPOS_1(20,i)] = 0;
215 		keys[GETPOS_1(21,i)] = 0;
216 		keys[GETPOS_1(22,i)] = 0;
217 		keys[GETPOS_1(23,i)] = 0;
218 	}
219 
220 	SIMDSHA1body(keys, keys32, NULL, SSEi_MIXED_IN|SSEi_FLAT_OUT);
221 
222 	// Now convert back into a 'flat' value, which is a flat array.
223 	for (i = 0; i < SHA1_LOOP_CNT; ++i)
224 		memcpy(final[i], DeriveKey(&keys[20*i], X1), cur_salt->keySize/8);
225 }
226 #else
227 // for non MMX, SHA1_LOOP_CNT is 1
GeneratePasswordHashUsingSHA1(int idx,unsigned char final[SHA1_LOOP_CNT][20])228 static void GeneratePasswordHashUsingSHA1(int idx, unsigned char final[SHA1_LOOP_CNT][20])
229 {
230 	unsigned char hashBuf[20], *key;
231 	UTF16 *passwordBuf=saved_key[idx];
232 	int passwordBufSize=saved_len[idx];
233 	/* H(0) = H(salt, password)
234 	 * hashBuf = SHA1Hash(salt, password);
235 	 * create input buffer for SHA1 from salt and unicode version of password */
236 	unsigned int inputBuf[(0x14 + 0x04 + 4) / sizeof(int)];
237 	unsigned char X1[20];
238 	int i;
239 	SHA_CTX ctx;
240 
241 	SHA1_Init(&ctx);
242 	SHA1_Update(&ctx, cur_salt->osalt, cur_salt->saltSize);
243 	SHA1_Update(&ctx, passwordBuf, passwordBufSize);
244 	SHA1_Final(hashBuf, &ctx);
245 
246 	/* Generate each hash in turn
247 	 * H(n) = H(i, H(n-1))
248 	 * hashBuf = SHA1Hash(i, hashBuf); */
249 
250 	// Create a byte array of the integer and put at the front of the input buffer
251 	// 1.3.6 says that little-endian byte ordering is expected
252 	memcpy(&inputBuf[1], hashBuf, 20);
253 	for (i = 0; i < MS_OFFICE_2007_ITERATIONS; i++) {
254 #if ARCH_LITTLE_ENDIAN
255 		*inputBuf = i;
256 #else
257 		*inputBuf = JOHNSWAP(i);
258 #endif
259 		// 'append' the previously generated hash to the input buffer
260 		SHA1_Init(&ctx);
261 		SHA1_Update(&ctx, inputBuf, 0x14 + 0x04);
262 		SHA1_Final((unsigned char*)&inputBuf[1], &ctx);
263 	}
264 	// Finally, append "block" (0) to H(n)
265 	// hashBuf = SHA1Hash(hashBuf, 0);
266 	memset(&inputBuf[6], 0, 4);
267 	SHA1_Init(&ctx);
268 	SHA1_Update(&ctx, &inputBuf[1], 0x14 + 0x04);
269 	SHA1_Final(hashBuf, &ctx);
270 
271 	key = DeriveKey(hashBuf, X1);
272 
273 	// Should handle the case of longer key lengths as shown in 2.3.4.9
274 	// Grab the key length bytes of the final hash as the encrypytion key
275 	memcpy(final[0], key, cur_salt->keySize/8);
276 }
277 #endif
278 
279 #ifdef SIMD_COEF_32
GenerateAgileEncryptionKey(int idx,unsigned char hashBuf[SHA1_LOOP_CNT][64])280 static void GenerateAgileEncryptionKey(int idx, unsigned char hashBuf[SHA1_LOOP_CNT][64])
281 {
282 	unsigned char tmpBuf[20];
283 	int hashSize = cur_salt->keySize >> 3;
284 	unsigned i, j;
285 	SHA_CTX ctx;
286 	unsigned char _IBuf[64*SHA1_LOOP_CNT+MEM_ALIGN_CACHE], *keys,
287 	              _OBuf[20*SHA1_LOOP_CNT+MEM_ALIGN_CACHE];
288 	uint32_t *keys32, (*crypt)[20/4];
289 
290 	crypt = (void*)mem_align(_OBuf, MEM_ALIGN_CACHE);
291 	keys = (unsigned char*)mem_align(_IBuf, MEM_ALIGN_CACHE);
292 	keys32 = (uint32_t*)keys;
293 	memset(keys, 0, 64*SHA1_LOOP_CNT);
294 
295 	for (i = 0; i < SHA1_LOOP_CNT; ++i) {
296 		SHA1_Init(&ctx);
297 		SHA1_Update(&ctx, cur_salt->osalt, cur_salt->saltSize);
298 		SHA1_Update(&ctx, saved_key[idx+i], saved_len[idx+i]);
299 		SHA1_Final(tmpBuf, &ctx);
300 		for (j = 4; j < 24; ++j)
301 			keys[GETPOS_1(j, i)] = tmpBuf[j-4];
302 		keys[GETPOS_1(j, i)] = 0x80;
303 		// 24 bytes of crypt data (192 bits).
304 		keys[GETPOS_1(63, i)] = 192;
305 	}
306 
307 	// we do 1 less than actual number of iterations here.
308 	for (i = 0; i < cur_salt->spinCount-1; i++) {
309 		for (j = 0; j < SHA1_LOOP_CNT; ++j) {
310 			keys[GETPOS_1(0, j)] = i&0xff;
311 			keys[GETPOS_1(1, j)] = (i>>8)&0xff;
312 			keys[GETPOS_1(2, j)] = i>>16;
313 		}
314 		// Here we output to 4 bytes past start of input buffer.
315 		SIMDSHA1body(keys, &keys32[SIMD_COEF_32], NULL, SSEi_MIXED_IN|SSEi_OUTPUT_AS_INP_FMT);
316 	}
317 	// last iteration is output to start of input buffer, then 32 bit 0 appended.
318 	// but this is still ends up being 24 bytes of crypt data.
319 	for (j = 0; j < SHA1_LOOP_CNT; ++j) {
320 		keys[GETPOS_1(0, j)] = i&0xff;
321 		keys[GETPOS_1(1, j)] = (i>>8)&0xff;
322 		keys[GETPOS_1(2, j)] = i>>16;
323 	}
324 	SIMDSHA1body(keys, keys32, NULL, SSEi_MIXED_IN|SSEi_OUTPUT_AS_INP_FMT);
325 
326 	// Finally, append "block" (0) to H(n)
327 	for (i = 0; i < SHA1_LOOP_CNT; ++i) {
328 		for (j = 0; j < 8; ++j)
329 			keys[GETPOS_1(20+j, i)] = encryptedVerifierHashInputBlockKey[j];
330 		keys[GETPOS_1(20+j, i)] = 0x80;
331 		// 28 bytes of crypt data (192 bits).
332 		keys[GETPOS_1(63, i)] = 224;
333 	}
334 	SIMDSHA1body(keys, (uint32_t*)crypt, NULL, SSEi_MIXED_IN|SSEi_FLAT_OUT);
335 	for (i = 0; i < SHA1_LOOP_CNT; ++i)
336 		memcpy(hashBuf[i], crypt[i], 20);
337 
338 	// And second "block" (0) to H(n)
339 	for (i = 0; i < SHA1_LOOP_CNT; ++i) {
340 		for (j = 0; j < 8; ++j)
341 			keys[GETPOS_1(20+j, i)] = encryptedVerifierHashValueBlockKey[j];
342 	}
343 	SIMDSHA1body(keys, (uint32_t*)crypt, NULL, SSEi_MIXED_IN|SSEi_FLAT_OUT);
344 	for (i = 0; i < SHA1_LOOP_CNT; ++i)
345 		memcpy(&hashBuf[i][32], crypt[i], 20);
346 
347 	// Fix up the size per the spec
348 	if (20 < hashSize) { // FIXME: Is this ever true?
349 		for (i = 0; i < SHA1_LOOP_CNT; ++i) {
350 			for (j = 20; j < hashSize; j++) {
351 				hashBuf[i][j] = 0x36;
352 				hashBuf[i][32 + j] = 0x36;
353 			}
354 		}
355 	}
356 }
357 #else
GenerateAgileEncryptionKey(int idx,unsigned char hashBuf[SHA1_LOOP_CNT][64])358 static void GenerateAgileEncryptionKey(int idx, unsigned char hashBuf[SHA1_LOOP_CNT][64])
359 {
360 	/* H(0) = H(salt, password)
361 	 * hashBuf = SHA1Hash(salt, password);
362 	 * create input buffer for SHA1 from salt and unicode version of password */
363 	UTF16 *passwordBuf=saved_key[idx];
364 	int passwordBufSize=saved_len[idx];
365 	int hashSize = cur_salt->keySize >> 3;
366 	unsigned int inputBuf[(28 + 4) / sizeof(int)];
367 	unsigned int i;
368 	SHA_CTX ctx;
369 
370 	SHA1_Init(&ctx);
371 	SHA1_Update(&ctx, cur_salt->osalt, cur_salt->saltSize);
372 	SHA1_Update(&ctx, passwordBuf, passwordBufSize);
373 	SHA1_Final(hashBuf[0], &ctx);
374 
375 	/* Generate each hash in turn
376 	 * H(n) = H(i, H(n-1))
377 	 * hashBuf = SHA1Hash(i, hashBuf); */
378 
379 	// Create a byte array of the integer and put at the front of the input buffer
380 	// 1.3.6 says that little-endian byte ordering is expected
381 	memcpy(&inputBuf[1], hashBuf[0], 20);
382 	for (i = 0; i < cur_salt->spinCount; i++) {
383 #if ARCH_LITTLE_ENDIAN
384 		*inputBuf = i;
385 #else
386 		*inputBuf = JOHNSWAP(i);
387 #endif
388 		// 'append' the previously generated hash to the input buffer
389 		SHA1_Init(&ctx);
390 		SHA1_Update(&ctx, inputBuf, 0x14 + 0x04);
391 		SHA1_Final((unsigned char*)&inputBuf[1], &ctx);
392 	}
393 	// Finally, append "block" (0) to H(n)
394 	memcpy(&inputBuf[6], encryptedVerifierHashInputBlockKey, 8);
395 	SHA1_Init(&ctx);
396 	SHA1_Update(&ctx, &inputBuf[1], 28);
397 	SHA1_Final(hashBuf[0], &ctx);
398 
399 	// And second "block" (0) to H(n)
400 	memcpy(&inputBuf[6], encryptedVerifierHashValueBlockKey, 8);
401 	SHA1_Init(&ctx);
402 	SHA1_Update(&ctx, &inputBuf[1], 28);
403 	SHA1_Final(&hashBuf[0][32], &ctx);
404 
405 	// Fix up the size per the spec
406 	if (20 < hashSize) { // FIXME: Is this ever true?
407 		for (i = 20; i < hashSize; i++) {
408 			hashBuf[0][i] = 0x36;
409 			hashBuf[0][32 + i] = 0x36;
410 		}
411 	}
412 }
413 #endif
414 
415 #ifdef SIMD_COEF_64
GenerateAgileEncryptionKey512(int idx,unsigned char hashBuf[SHA512_LOOP_CNT][128])416 static void GenerateAgileEncryptionKey512(int idx, unsigned char hashBuf[SHA512_LOOP_CNT][128])
417 {
418 	unsigned char tmpBuf[64];
419 	unsigned int i, j, k;
420 	SHA512_CTX ctx;
421 	unsigned char _IBuf[128*SHA512_LOOP_CNT+MEM_ALIGN_CACHE], *keys,
422 	              _OBuf[64*SHA512_LOOP_CNT+MEM_ALIGN_CACHE];
423 	uint64_t *keys64, (*crypt)[64/8];
424 	uint32_t *keys32, *crypt32;
425 
426 	crypt = (void*)mem_align(_OBuf, MEM_ALIGN_CACHE);
427 	keys = (unsigned char*)mem_align(_IBuf, MEM_ALIGN_CACHE);
428 	keys64 = (uint64_t*)keys;
429 	keys32 = (uint32_t*)keys;
430 	crypt32 = (uint32_t*)crypt;
431 
432 	memset(keys, 0, 128*SHA512_LOOP_CNT);
433 	for (i = 0; i < SHA512_LOOP_CNT; ++i) {
434 		SHA512_Init(&ctx);
435 		SHA512_Update(&ctx, cur_salt->osalt, cur_salt->saltSize);
436 		SHA512_Update(&ctx, saved_key[idx+i], saved_len[idx+i]);
437 		SHA512_Final(tmpBuf, &ctx);
438 		for (j = 4; j < 68; ++j)
439 			keys[GETPOS_512(j, i)] = tmpBuf[j-4];
440 		keys[GETPOS_512(j, i)] = 0x80;
441 		// 68 bytes of crypt data (0x220 bits).
442 		keys[GETPOS_512(127, i)] = 0x20;
443 		keys[GETPOS_512(126, i)] = 0x02;
444 	}
445 
446 	// we do 1 less than actual number of iterations here.
447 	for (i = 0; i < cur_salt->spinCount-1; i++) {
448 
449 		// Iteration counter in first 4 bytes
450 		for (j = 0; j < SHA512_LOOP_CNT; j++) {
451 			keys[GETPOS_512(0, j)] = i & 0xFF;
452 			keys[GETPOS_512(1, j)] = (i>>8) & 0xFF;
453 			keys[GETPOS_512(2, j)] = (i>>16) & 0xFF;
454 			keys[GETPOS_512(3, j)] = (i>>24) & 0xFF;
455 		}
456 
457 		SIMDSHA512body(keys, (uint64_t*)crypt, NULL, SSEi_MIXED_IN);
458 
459 		// Then we output to 4 bytes past start of input buffer.
460 
461 		/* Original code to copy in 64 bytes into offset 4.  Not BE compatible.
462 		for (j = 0; j < SHA512_LOOP_CNT; j++) {
463 			uint32_t *o = keys32 + (j&(SIMD_COEF_64-1))*2 + j/SIMD_COEF_64*2*SHA_BUF_SIZ*SIMD_COEF_64;
464 			uint32_t *in = crypt32 + (j&(SIMD_COEF_64-1))*2 + j/SIMD_COEF_64*2*8*SIMD_COEF_64;
465 
466 			for (k = 0; k < 8; k++) {
467 				o[0] = in[1];
468 				o += SIMD_COEF_64*2;
469 				o[1] = in[0];
470 				in += SIMD_COEF_64*2;
471 			}
472 		}
473 		*/
474 
475 		/* First shot: works good, not endianity bound, but is SLOWER (1/2 speed)
476 		for (j = 0; j < SHA512_LOOP_CNT; j++) {
477 			for (k = 0; k < 64; k++) {
478 				keys[GETPOS_512((k+4), j)] = ((unsigned char*)crypt)[GETOUTPOS_512(k,j)];
479 			}
480 		}
481 		*/
482 
483 
484 		// tweaked original code, swapping uint32_t and this works.
485 		// it is very likely this code could be optimized even more, by handling data
486 		// in uint64_t items. First and last would still need handled in uint32, but
487 		// other 7 elements could be done by reading 2 8 byte values from crypt, shifting
488 		// and then placing at one time into input buffer.   I might look into doing that
489 		// and see if there is any improvement.  It may also be benefical to look at using
490 		// flat buffers here.  Flat buffers would be trivial.  a simple memcpy to move all
491 		// 64 bytes at once.  NOTE, in flat model, there is NO way to do this using any
492 		// 64 bit assignments. Either the input buffer, or the crypt buffer would not be
493 		// properly aligned.  So memcpy would have to be used. BUT it should be trivial
494 		// and may in the end be a faster solution, than keeping this code in mixed form.
495 		// but for now, it will be left as a task for someone else.
496 		for (j = 0; j < SHA512_LOOP_CNT; j++) {
497 			uint32_t *o = keys32 + (j&(SIMD_COEF_64-1))*2 + j/SIMD_COEF_64*2*SHA_BUF_SIZ*SIMD_COEF_64;
498 			uint32_t *in = crypt32 + (j&(SIMD_COEF_64-1))*2 + j/SIMD_COEF_64*2*8*SIMD_COEF_64;
499 
500 			for (k = 0; k < 8; k++) {
501 #if ARCH_LITTLE_ENDIAN==1
502 				o[0] = in[1];
503 				o += SIMD_COEF_64*2;
504 				o[1] = in[0];
505 				in += SIMD_COEF_64*2;
506 #else
507 				o[1] = in[0];
508 				o += SIMD_COEF_64*2;
509 				o[0] = in[1];
510 				in += SIMD_COEF_64*2;
511 #endif
512 			}
513 		}
514 	}
515 	// last iteration is output to start of input buffer, then 32 bit 0 appended.
516 	// but this is still ends up being 24 bytes of crypt data.
517 	for (j = 0; j < SHA512_LOOP_CNT; ++j) {
518 		keys[GETPOS_512(0, j)] = i&0xff;
519 		keys[GETPOS_512(1, j)] = (i>>8)&0xff;
520 		keys[GETPOS_512(2, j)] = i>>16;
521 	}
522 	SIMDSHA512body(keys, keys64, NULL, SSEi_MIXED_IN|SSEi_OUTPUT_AS_INP_FMT);
523 
524 	// Finally, append "block" (0) to H(n)
525 	for (i = 0; i < SHA512_LOOP_CNT; ++i) {
526 		for (j = 0; j < 8; ++j)
527 			keys[GETPOS_512(64+j, i)] = encryptedVerifierHashInputBlockKey[j];
528 		keys[GETPOS_512(64+j, i)] = 0x80;
529 		// 72 bytes of crypt data (0x240  we already have 0x220 here)
530 		keys[GETPOS_512(127, i)] = 0x40;
531 	}
532 	SIMDSHA512body(keys, (uint64_t*)crypt, NULL, SSEi_MIXED_IN|SSEi_FLAT_OUT);
533 	for (i = 0; i < SHA512_LOOP_CNT; ++i)
534 		memcpy((uint64_t*)(hashBuf[i]), crypt[i], 64);
535 
536 	// And second "block" (0) to H(n)
537 	for (i = 0; i < SHA512_LOOP_CNT; ++i) {
538 		for (j = 0; j < 8; ++j)
539 			keys[GETPOS_512(64+j, i)] = encryptedVerifierHashValueBlockKey[j];
540 	}
541 	SIMDSHA512body(keys, (uint64_t*)crypt, NULL, SSEi_MIXED_IN|SSEi_FLAT_OUT);
542 
543 	for (i = 0; i < SHA512_LOOP_CNT; ++i)
544 		memcpy((uint64_t*)(&hashBuf[i][64]), crypt[i], 64);
545 }
546 #else
GenerateAgileEncryptionKey512(int idx,unsigned char hashBuf[SHA512_LOOP_CNT][128])547 static void GenerateAgileEncryptionKey512(int idx, unsigned char hashBuf[SHA512_LOOP_CNT][128])
548 {
549 	UTF16 *passwordBuf=saved_key[idx];
550 	int passwordBufSize=saved_len[idx];
551 	unsigned int inputBuf[128 / sizeof(int)];
552 	int i;
553 	SHA512_CTX ctx;
554 
555 	SHA512_Init(&ctx);
556 	SHA512_Update(&ctx, cur_salt->osalt, cur_salt->saltSize);
557 	SHA512_Update(&ctx, passwordBuf, passwordBufSize);
558 	SHA512_Final(hashBuf[0], &ctx);
559 
560 	// Create a byte array of the integer and put at the front of the input buffer
561 	// 1.3.6 says that little-endian byte ordering is expected
562 	memcpy(&inputBuf[1], hashBuf, 64);
563 	for (i = 0; i < cur_salt->spinCount; i++) {
564 #if ARCH_LITTLE_ENDIAN
565 		*inputBuf = i;
566 #else
567 		*inputBuf = JOHNSWAP(i);
568 #endif
569 		// 'append' the previously generated hash to the input buffer
570 		SHA512_Init(&ctx);
571 		SHA512_Update(&ctx, inputBuf, 64 + 0x04);
572 		SHA512_Final((unsigned char*)&inputBuf[1], &ctx);
573 	}
574 
575 	// Finally, append "block" (0) to H(n)
576 	memcpy(&inputBuf[68/4], encryptedVerifierHashInputBlockKey, 8);
577 	SHA512_Init(&ctx);
578 	SHA512_Update(&ctx, &inputBuf[1], 64 + 8);
579 	SHA512_Final(hashBuf[0], &ctx);
580 	// And second "block" (0) to H(n)
581 	memcpy(&inputBuf[68/4], encryptedVerifierHashValueBlockKey, 8);
582 	SHA512_Init(&ctx);
583 	SHA512_Update(&ctx, &inputBuf[1], 64 + 8);
584 	SHA512_Final(&hashBuf[0][64], &ctx);
585 }
586 #endif
587 
init(struct fmt_main * self)588 static void init(struct fmt_main *self)
589 {
590 	omp_autotune(self, OMP_SCALE);
591 
592 	saved_key = mem_calloc(sizeof(*saved_key), self->params.max_keys_per_crypt);
593 	saved_len = mem_calloc(sizeof(*saved_len), self->params.max_keys_per_crypt);
594 	crypt_key = mem_calloc(sizeof(*crypt_key), self->params.max_keys_per_crypt);
595 	cracked = mem_calloc(sizeof(*cracked), self->params.max_keys_per_crypt);
596 	if (options.target_enc == UTF_8)
597 		self->params.plaintext_length = MIN(125, PLAINTEXT_LENGTH * 3);
598 }
599 
done(void)600 static void done(void)
601 {
602 	MEM_FREE(cracked);
603 	MEM_FREE(crypt_key);
604 	MEM_FREE(saved_len);
605 	MEM_FREE(saved_key);
606 }
607 
set_salt(void * salt)608 static void set_salt(void *salt)
609 {
610 	cur_salt = (ms_office_custom_salt *)salt;
611 }
612 
DecryptUsingSymmetricKeyAlgorithm(ms_office_custom_salt * cur_salt,unsigned char * verifierInputKey,unsigned char * encryptedVerifier,const unsigned char * decryptedVerifier,int length)613 static void DecryptUsingSymmetricKeyAlgorithm(ms_office_custom_salt *cur_salt, unsigned char *verifierInputKey, unsigned char *encryptedVerifier, const unsigned char *decryptedVerifier, int length)
614 {
615 	unsigned char iv[32];
616 	AES_KEY akey;
617 
618 	memcpy(iv, cur_salt->osalt, 16);
619 	memset(&iv[16], 0, 16);
620 	AES_set_decrypt_key(verifierInputKey, cur_salt->keySize, &akey);
621 	AES_cbc_encrypt(encryptedVerifier, (unsigned char*)decryptedVerifier, length, &akey, iv, AES_DECRYPT);
622 }
623 
624 // We now pass in the 16 byte 'output'. The older code has been kept, but
625 // it no longer used that way. We used to return the 'cracked' value, i.e.
626 // if it matched, return 1, else 0. Now we store the encryption data to out,
627 // and then in the format use normal binary_hash() methods to test it. The
628 // old method used decryption (of the encrypted field). Now we use encrption
629 // of the plaintext data, and then binary_hash() compares that to the known
630 // encrypted field data.
631 // For the time being, the original code has been kept (commented out). I am
632 // doing this in hopes of figuring out some way to salt-dupe correct the
633 // office 2010-2013 formats. I do not think they can be done, but I may be
634 // wrong, so I will keep this code in an "easy to see what changed" layout.
PasswordVerifier(ms_office_custom_salt * cur_salt,unsigned char * key,uint32_t * out)635 static void PasswordVerifier(ms_office_custom_salt *cur_salt, unsigned char *key, uint32_t *out)
636 {
637 	unsigned char decryptedVerifier[16];
638 	//unsigned char decryptedVerifierHash[16];
639 	AES_KEY akey;
640 	SHA_CTX ctx;
641 	unsigned char checkHash[32];
642 	unsigned char checkHashed[32];
643 
644 	AES_set_decrypt_key(key, 128, &akey);
645 	AES_ecb_encrypt(cur_salt->encryptedVerifier, decryptedVerifier, &akey, AES_DECRYPT);
646 
647 	// Not using cracked any more.
648 	SHA1_Init(&ctx);
649 	SHA1_Update(&ctx, decryptedVerifier, 16);
650 	SHA1_Final(checkHash, &ctx);
651 	AES_set_encrypt_key(key, 128, &akey);
652 	AES_ecb_encrypt(checkHash, checkHashed, &akey, AES_ENCRYPT);
653 	memcpy(out, checkHashed, 16);
654 
655 	//AES_set_decrypt_key(key, 128, &akey);
656 	//AES_ecb_encrypt(cur_salt->encryptedVerifierHash, decryptedVerifierHash, &akey, AES_DECRYPT);
657 	//
658 	///* find SHA1 hash of decryptedVerifier */
659 	//SHA1_Init(&ctx);
660 	//SHA1_Update(&ctx, decryptedVerifier, 16);
661 	//SHA1_Final(checkHash, &ctx);
662 	//
663 	//return !memcmp(checkHash, decryptedVerifierHash, 16);
664 }
665 
crypt_all(int * pcount,struct db_salt * salt)666 static int crypt_all(int *pcount, struct db_salt *salt)
667 {
668 	const int count = *pcount;
669 	int index = 0, inc = SHA1_LOOP_CNT;
670 
671 	if (cur_salt->version == 2013)
672 		inc = SHA512_LOOP_CNT;
673 
674 #ifdef _OPENMP
675 #pragma omp parallel for
676 #endif
677 	for (index = 0; index < count; index+=inc)
678 	{
679 		int i;
680 		if (cur_salt->version == 2007) {
681 			unsigned char encryptionKey[SHA1_LOOP_CNT][20];
682 			GeneratePasswordHashUsingSHA1(index, encryptionKey);
683 			for (i = 0; i < SHA1_LOOP_CNT; ++i)
684 				PasswordVerifier(cur_salt, encryptionKey[i], crypt_key[index+i]);
685 		}
686 		else if (cur_salt->version == 2010) {
687 			unsigned char verifierKeys[SHA1_LOOP_CNT][64], decryptedVerifierHashInputBytes[16], decryptedVerifierHashBytes[32];
688 			unsigned char hash[20];
689 			SHA_CTX ctx;
690 			GenerateAgileEncryptionKey(index, verifierKeys);
691 			for (i = 0; i < inc; ++i) {
692 				DecryptUsingSymmetricKeyAlgorithm(cur_salt, verifierKeys[i], cur_salt->encryptedVerifier, decryptedVerifierHashInputBytes, 16);
693 				DecryptUsingSymmetricKeyAlgorithm(cur_salt, &verifierKeys[i][32], cur_salt->encryptedVerifierHash, decryptedVerifierHashBytes, 32);
694 				SHA1_Init(&ctx);
695 				SHA1_Update(&ctx, decryptedVerifierHashInputBytes, 16);
696 				SHA1_Final(hash, &ctx);
697 				cracked[index+i] = !memcmp(hash, decryptedVerifierHashBytes, 20);
698 			}
699 		}
700 		else if (cur_salt->version == 2013) {
701 			unsigned char verifierKeys[SHA512_LOOP_CNT][128], decryptedVerifierHashInputBytes[16], decryptedVerifierHashBytes[32];
702 			unsigned char hash[64];
703 			SHA512_CTX ctx;
704 			GenerateAgileEncryptionKey512(index, verifierKeys);
705 			for (i = 0; i < inc; ++i) {
706 				DecryptUsingSymmetricKeyAlgorithm(cur_salt, verifierKeys[i], cur_salt->encryptedVerifier, decryptedVerifierHashInputBytes, 16);
707 				DecryptUsingSymmetricKeyAlgorithm(cur_salt, &verifierKeys[i][64], cur_salt->encryptedVerifierHash, decryptedVerifierHashBytes, 32);
708 				SHA512_Init(&ctx);
709 				SHA512_Update(&ctx, decryptedVerifierHashInputBytes, 16);
710 				SHA512_Final(hash, &ctx);
711 				cracked[index+i] = !memcmp(hash, decryptedVerifierHashBytes, 20);
712 			}
713 		}
714 	}
715 	return count;
716 }
717 
cmp_all(void * binary,int count)718 static int cmp_all(void *binary, int count)
719 {
720 	int index;
721 	if (cur_salt->version == 2007) {
722 		for (index = 0; index < count; index++) {
723 			if ( ((uint32_t*)binary)[0] == crypt_key[index][0] )
724 				return 1;
725 		}
726 		return 0;
727 	}
728 	for (index = 0; index < count; index++)
729 		if (cracked[index])
730 			return 1;
731 	return 0;
732 }
733 
cmp_one(void * binary,int index)734 static int cmp_one(void *binary, int index)
735 {
736 	if (cur_salt->version == 2007) {
737 		return !memcmp(binary, crypt_key[index], BINARY_SIZE);
738 	}
739 	return cracked[index];
740 }
741 
cmp_exact(char * source,int index)742 static int cmp_exact(char *source, int index)
743 {
744 	return 1;
745 }
746 
get_hash_0(int index)747 static int get_hash_0(int index) { if (cur_salt->version!=2007) return 0; return crypt_key[index][0] & PH_MASK_0; }
get_hash_1(int index)748 static int get_hash_1(int index) { if (cur_salt->version!=2007) return 0; return crypt_key[index][0] & PH_MASK_1; }
get_hash_2(int index)749 static int get_hash_2(int index) { if (cur_salt->version!=2007) return 0; return crypt_key[index][0] & PH_MASK_2; }
get_hash_3(int index)750 static int get_hash_3(int index) { if (cur_salt->version!=2007) return 0; return crypt_key[index][0] & PH_MASK_3; }
get_hash_4(int index)751 static int get_hash_4(int index) { if (cur_salt->version!=2007) return 0; return crypt_key[index][0] & PH_MASK_4; }
get_hash_5(int index)752 static int get_hash_5(int index) { if (cur_salt->version!=2007) return 0; return crypt_key[index][0] & PH_MASK_5; }
get_hash_6(int index)753 static int get_hash_6(int index) { if (cur_salt->version!=2007) return 0; return crypt_key[index][0] & PH_MASK_6; }
754 
office_set_key(char * key,int index)755 static void office_set_key(char *key, int index)
756 {
757 	/* convert key to UTF-16LE */
758 	saved_len[index] = enc_to_utf16(saved_key[index], PLAINTEXT_LENGTH, (UTF8*)key, strlen(key));
759 	if (saved_len[index] < 0)
760 		saved_len[index] = strlen16(saved_key[index]);
761 	saved_len[index] <<= 1;
762 }
763 
get_key(int index)764 static char *get_key(int index)
765 {
766 	return (char*)utf16_to_enc(saved_key[index]);
767 }
768 
769 struct fmt_main fmt_office = {
770 	{
771 		FORMAT_LABEL,
772 		FORMAT_NAME,
773 		ALGORITHM_NAME,
774 		BENCHMARK_COMMENT,
775 		BENCHMARK_LENGTH,
776 		0,
777 		PLAINTEXT_LENGTH,
778 		BINARY_SIZE,
779 		BINARY_ALIGN,
780 		SALT_SIZE,
781 		SALT_ALIGN,
782 		MIN_KEYS_PER_CRYPT,
783 		MAX_KEYS_PER_CRYPT,
784 		FMT_CASE | FMT_8_BIT | FMT_OMP | FMT_UNICODE | FMT_ENC,
785 		{
786 			"MS Office version",
787 			"iteration count",
788 		},
789 		{ FORMAT_TAG_OFFICE },
790 		office_tests
791 	}, {
792 		init,
793 		done,
794 		fmt_default_reset,
795 		fmt_default_prepare,
796 		ms_office_common_valid,
797 		fmt_default_split,
798 		ms_office_common_binary,
799 		ms_office_common_get_salt,
800 		{
801 			ms_office_common_version,
802 			ms_office_common_iteration_count,
803 		},
804 		fmt_default_source,
805 		{
806 			fmt_default_binary_hash_0,
807 			fmt_default_binary_hash_1,
808 			fmt_default_binary_hash_2,
809 			fmt_default_binary_hash_3,
810 			fmt_default_binary_hash_4,
811 			fmt_default_binary_hash_5,
812 			fmt_default_binary_hash_6
813 		},
814 		fmt_default_salt_hash,
815 		NULL,
816 		set_salt,
817 		office_set_key,
818 		get_key,
819 		fmt_default_clear_keys,
820 		crypt_all,
821 		{
822 			get_hash_0,
823 			get_hash_1,
824 			get_hash_2,
825 			get_hash_3,
826 			get_hash_4,
827 			get_hash_5,
828 			get_hash_6
829 		},
830 		cmp_all,
831 		cmp_one,
832 		cmp_exact
833 	}
834 };
835 
836 #endif /* plugin stanza */
837