1 /* vim: set ts=8 sts=4 sw=4 tw=80 noet: */
2 /*======================================================================
3 Copyright (C) 2004,2005,2009,2011 Walter Doekes <walter+tthsum@wjd.nu>
4 This file is part of tthsum.
5 
6 tthsum is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10 
11 tthsum is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with tthsum.  If not, see <http://www.gnu.org/licenses/>.
18 ======================================================================*/
19 #include "thex.h"
20 
21 #include "base32.h"
22 #include "test.h"
23 #include <string.h>
24 
25 
thex_cmp(struct rofile * stream,const char * base32)26 static int thex_cmp(struct rofile* stream, const char* base32) {
27     /* Don't forget to zero out cmpres/tstres */
28     uint64_t cmpres[3] = {_ULL(0), _ULL(0), _ULL(0)};
29     uint64_t tstres[3] = {_ULL(0), _ULL(0), _ULL(0)};
30     char tstbase32[40];
31     if (base32touint64(&cmpres[0], base32, 3) == -1)
32 	FAIL1("base32touint64 returned -1 on %s", base32);
33     if (thex_tiger_root(stream, &tstres[0], NULL) == -1)
34 	FAIL1("thex_tiger_root returned -1 on %s", base32);
35     if (uint64tobase32(tstbase32, tstres, 3) == -1)
36 	FAIL1("uint64tobase32 returned -1 on %s", base32);
37     if (memcmp(&cmpres[0], &tstres[0], 3 * sizeof(uint64_t)) != 0) {
38 	unsigned i;
39 	char hexbuf[49];
40 	memset(hexbuf, '.', 48);
41 	hexbuf[48] = '\0';
42 	for (i = 0; i < 3 * sizeof(uint64_t); ++i) {
43 	    char cmphigh = (char)(*(((uint8_t*)&cmpres[0]) + i) >> 4);
44 	    char cmplow = (char)(*(((uint8_t*)&cmpres[0]) + i) & 0xf);
45 	    char tsthigh = (char)(*(((uint8_t*)&tstres[0]) + i) >> 4);
46 	    char tstlow = (char)(*(((uint8_t*)&tstres[0]) + i) & 0xf);
47 	    if (cmphigh != tsthigh)
48 		hexbuf[2*i] = tsthigh >= 10 ? 'a'+(tsthigh-10) : '0'+tsthigh;
49 	    if (cmplow != tstlow)
50 		hexbuf[2*i+1] = tstlow >= 10 ? 'a'+(tstlow-10) : '0'+tstlow;
51 	}
52 	FAIL3("memcmp: mismatch on %s != %s: %s", base32, tstbase32, hexbuf);
53     }
54     return 0;
55 }
56 
thex_memcmp(const char * data,unsigned length,const char * base32)57 static int thex_memcmp(const char* data, unsigned length, const char* base32) {
58     int ret;
59     struct rofile* stream;
60     stream = rofopen_mem(data, length);
61     if (stream == NULL)
62 	FAIL1("rofopen_mem failed on %s", base32);
63     ret = thex_cmp(stream, base32);
64     rofclose(stream);
65     return ret;
66 }
67 
thex_strcmp(const char * str,const char * base32)68 static int thex_strcmp(const char* str, const char* base32) {
69     return thex_memcmp(str, strlen(str), base32);
70 }
71 
test_standard_hashes()72 static int test_standard_hashes() {
73     char buf[1026];
74     int i;
75     for (i = 0; i < 1025; ++i)
76 	buf[i] = 'A';
77     buf[1025] = '\0';
78 
79     return thex_strcmp("", "LWPNACQDBZRYXW3VHJVCJ64QBZNGHOHHHZWCLNQ")
80 	 + thex_memcmp("\0", 1, "VK54ZIEEVTWNAUI5D5RDFIL37LX2IQNSTAXFKSA")
81 	 + thex_memcmp(buf, 1024, "L66Q4YVNAFWVS23X2HJIRA5ZJ7WXR3F26RSASFA")
82 	 + thex_memcmp(buf, 1025, "PZMRYHGY6LTBEH63ZWAHDORHSYTLO4LEFUIKHWY");
83 }
84 
test_extra_hashes()85 static int test_extra_hashes() {
86 #define buflen (20 * 1024 * 28) /* \x00A-Z\xFF */
87     char buf[buflen];
88     int i;
89     for (i = 0; i < buflen; i += 28)
90 	memcpy(buf + i, "\x00" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "\xff", 28);
91     return thex_strcmp("abcdefghijklmnopqrstuvwxyz",
92 	    "LMHNA2VYO465P2RDOGTR2CL6XKHZNI2X4CCUY5Y")
93 	+ thex_memcmp("\xff\x00\x01", 3,
94 	    "BRA2Y3Q5YXZKONQOTBA5BMIWTWMFVFISP3AFLUY")
95 	+ thex_memcmp(buf, buflen, /* 573440 */
96 	    "YWCGBHG5J26IDNFH3M55MR7674GYLSBXBWITCZA")
97 	+ thex_memcmp(buf, buflen - 5463, /* 567977 */
98 	    "OQMPMBCCCTSJJSKNO3FGFZX4T636THZB57UT7HI");
99 #undef buflen
100 }
101 
test_pavelch_hashes()102 static int test_pavelch_hashes() {
103     char buf[256];
104     int i;
105     for (i = 0; i < 256; ++i)
106 	buf[i] = (char)i;
107     return thex_memcmp(buf, 125, "B5LOOSIJN7KWAWIJUJPNHKLCZ5TGDZ34NKB7LVA")
108 	+ thex_memcmp(buf, 126, "UFWW3Q7PYSXGWUACF6C5F4377A4BYNUM5JENX6Y")
109 	+ thex_memcmp(buf, 127, "YJ6JWRX74NIKSRYWR2MVUEHF2K2RKUEHDK6MG7I")
110 	+ thex_memcmp(buf, 128, "ZU6NIYQCFYZKUZHOJABKACHEQV7GQMT75Q7H6MQ")
111 	+ thex_memcmp(buf, 129, "3YDAQRYUVS5DZNQWTJNXIQZ65PJV22VQ6HEY32I")
112 	/* +1 */
113 	+ thex_memcmp(buf + 1, 125, "CXMZBH4NNFUJ47TYUDNZFAMUUWLCHZZFHKU5IAA")
114 	+ thex_memcmp(buf + 1, 126, "3Y4VRHOMBRSUQZ4UHAAZI24YRCZUOUTCPHFBLPI")
115 	+ thex_memcmp(buf + 1, 127, "GT5HY5HOM7A7SLAL4HH5JMXUNIKP7OMZMBESL5Q")
116 	+ thex_memcmp(buf + 1, 128, "32RM6ILFACIWWHX4JGFYI5U5CD6CUTYFDHR5POI")
117 	+ thex_memcmp(buf + 1, 129, "DGD6BKKGH3AQUVA7DDOZWS2LRPYTCG5C23GNLKA")
118 	/* +2 */
119 	+ thex_memcmp(buf + 2, 125, "LGBYVEKTCQ5FYMU4XDQN2CN63J3JDFY4IABMETA")
120 	+ thex_memcmp(buf + 2, 126, "T7IEE2ZZJ3XI2QUSJSKOKXGC74KFT44M5FSX6WA")
121 	+ thex_memcmp(buf + 2, 127, "7KWOAII6AEAV67SK2ACZMN3HTN2ZYBNRSSUKGLA")
122 	+ thex_memcmp(buf + 2, 128, "XRTRHLCALO34QVC6NSXY4JTSC6THMGFXRUIW72I")
123 	+ thex_memcmp(buf + 2, 129, "O74RH63EWYNJHAFE7PXUF3JD4LQWGJOGLS4UU4Q")
124 	/* last */
125 	+ thex_memcmp(buf, 254, "V7NMKNTONQNSWUQENDMHVLPFLIXKGDDQBIWJHYA")
126 	+ thex_memcmp(buf, 255, "A7NQ5IZLVIPPHVDFAFHA5TDSBYJ5MKYTQMRJNBA")
127 	+ thex_memcmp(buf, 256, "YAJKVS45WRYJNA3IO4FWTYFXNTDHBEWMDGU465I")
128 	+ thex_memcmp(buf + 1, 254, "SCIIV6BFYPFII5GNTWGEEAPBUEXJOYYP67LOGVA")
129 	+ thex_memcmp(buf + 1, 255, "UMC6OJR6MLYN6ZWWL2XM5CQC7TROEI4P67C4PJQ")
130 	+ thex_memcmp(buf + 2, 254, "7HJFO26TDOH6T3KDYSI37EAXLYN3KL6SZBQLZMY");
131 }
132 
133 
134 TESTS(thex_test)
135     TEST(test_standard_hashes);
136     TEST(test_extra_hashes);
137     TEST(test_pavelch_hashes);
138 ENDTESTS
139