1 /* vim: set ts=8 sts=4 sw=4 tw=80 noet: */
2 /*======================================================================
3 Copyright (C) 2004,2005,2009 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 "base32.h"
20 
21 #include "test.h"
22 #include <string.h>
23 
24 #ifdef USE_TEXTS
25 #   include "texts.h"
26 #else /* !USE_TEXTS */
27 #   define get_error() "Fail"
28 #endif /* !USE_TEXTS */
29 
30 
help_cmp_symmetric8(const char * name,const uint8_t * uint8,unsigned uint8len,const char * base32,int should_fail)31 static int help_cmp_symmetric8(const char* name, const uint8_t* uint8,
32 	unsigned uint8len, const char* base32, int should_fail) {
33     uint8_t uint8buf[2048];
34     char base32buf[2048];
35     memset(uint8buf, 0, 2048);
36     memset(base32buf, 85, 2048);
37 
38     if (uint8len >= 1024 || strlen(base32) >= 2048)
39 	FAIL3("Test values too large: \"%s\" is %u and %u bytes", name,
40 		uint8len, (unsigned)strlen(base32));
41     if (uint8tobase32(base32buf, uint8, uint8len) != 0)
42 	FAIL2("uint8tobase32 failed on \"%s\": %s", name, get_error());
43     if (base32touint8(uint8buf, base32, uint8len) != 0)
44 	FAIL2("base32touint8 failed on \"%s\": %s", name, get_error());
45     if ((memcmp(uint8, uint8buf, uint8len) != 0
46 	    || strcmp(base32, base32buf) != 0) == !should_fail)
47 	FAIL2("Values %sdiffer for \"%s\"", should_fail ? "do NOT " : "", name);
48 
49     return 0;
50 }
51 
help_cmp_symmetric64(const char * name,const uint64_t * uint64,unsigned uint64len,const char * base32,int should_fail)52 static int help_cmp_symmetric64(const char* name, const uint64_t* uint64,
53 	unsigned uint64len, const char* base32, int should_fail) {
54     uint64_t uint64buf[2048];
55     char base32buf[2048];
56     memset(uint64buf, 0, 2048);
57     memset(base32buf, 85, 2048);
58 
59     if (uint64len >= 1024 / 8 || strlen(base32) >= 2048)
60 	FAIL3("Test values too large: \"%s\" is %u*8 and %u bytes", name,
61 		uint64len, (unsigned)strlen(base32));
62     if (uint64tobase32(base32buf, uint64, uint64len) != 0)
63 	FAIL2("uint64tobase32 failed on \"%s\": %s", name, get_error());
64     if (base32touint64(uint64buf, base32, uint64len) != 0)
65 	FAIL2("base32touint64 failed on \"%s\": %s", name, get_error());
66     if ((memcmp(uint64, uint64buf, uint64len) != 0
67 	    || strcmp(base32, base32buf) != 0) == !should_fail)
68 	FAIL2("Values %sdiffer for \"%s\"", should_fail ? "do NOT " : "", name);
69 
70     return 0;
71 }
72 
help_cmp_symmetric(const char * string,const char * base32)73 static int help_cmp_symmetric(const char* string, const char* base32) {
74     return help_cmp_symmetric8(string, (const uint8_t*)string,
75 	    strlen(string), base32, 0);
76 }
77 
help_not_cmp_symmetric(const char * string,const char * base32)78 static int help_not_cmp_symmetric(const char* string, const char* base32) {
79     return help_cmp_symmetric8(string, (const uint8_t*)string,
80 	    strlen(string), base32, 1);
81 }
82 
help_cmp_decode8(const char * name,const char * base32,const uint8_t * uint8,unsigned uint8len,int should_fail)83 static int help_cmp_decode8(const char* name, const char* base32,
84 	const uint8_t* uint8, unsigned uint8len, int should_fail) {
85     uint8_t uint8buf[2048];
86     memset(uint8buf, 0, 2048);
87 
88     if (uint8len > 1024)
89 	FAIL2("Test value too large: \"%s\" is %u bytes", name, uint8len);
90     if (base32touint8(uint8buf, base32, uint8len) != 0)
91 	FAIL1("base32touint8 failed on \"%s\"", name);
92     if (memcmp(uint8, uint8buf, uint8len) == !should_fail)
93 	FAIL2("Values %sdiffer for \"%s\"", should_fail ? "do NOT " : "", name);
94 
95     return 0;
96 }
97 
help_cmp_decode(const char * base32,const char * string)98 static int help_cmp_decode(const char* base32, const char* string) {
99     return help_cmp_decode8(base32, base32, (const uint8_t*)string,
100 	    strlen(string), 0);
101 }
102 
test_bidirectional_rfc4648()103 static int test_bidirectional_rfc4648() {
104     return help_cmp_symmetric("", "")
105 	    + help_cmp_symmetric("f", "MY")
106 	    + help_cmp_symmetric("fo", "MZXQ")
107 	    + help_cmp_symmetric("foo", "MZXW6")
108 	    + help_cmp_symmetric("foob", "MZXW6YQ")
109 	    + help_cmp_symmetric("fooba", "MZXW6YTB")
110 	    + help_cmp_symmetric("foobar", "MZXW6YTBOI");
111 }
112 
test_not_bidirectional_rfc4648()113 static int test_not_bidirectional_rfc4648() {
114     return help_not_cmp_symmetric("", "a")
115 	    + help_not_cmp_symmetric("g", "MY")
116 	    + help_not_cmp_symmetric("go", "MZXQ")
117 	    + help_not_cmp_symmetric("goo", "MZXW6")
118 	    + help_not_cmp_symmetric("fooB", "MZXW6YQ")
119 	    + help_not_cmp_symmetric("fooBa", "MZXW6YTB")
120 	    + help_not_cmp_symmetric("fooBar", "MZXW6YTBOI")
121 	    + help_not_cmp_symmetric("fooba", "MZXW6YTBOI")
122 	    + help_not_cmp_symmetric("foob", "MZXW6YTB")
123 	    + help_not_cmp_symmetric("foo", "MZXW6YQ");
124 }
125 
test_unidirectional_rfc4648()126 static int test_unidirectional_rfc4648() {
127    return help_cmp_decode("====", "")
128 	    + help_cmp_decode("my====", "f")
129 	    + help_cmp_decode("mY", "f")
130 	    + help_cmp_decode("mZxW6yTbOi====", "foobar");
131 }
132 
test_decode_success()133 static int test_decode_success() {
134     uint8_t buf[256];
135     return base32touint8(buf, "AA", 1)
136 	|| base32touint8(buf, "77", 1)
137 	|| base32touint8(buf, "777", 1)
138 	|| base32touint8(buf, "7777", 2)
139 	|| base32touint8(buf, "77777", 3)
140 	|| base32touint8(buf, "AAAAAA", 3)
141 	|| base32touint8(buf, "CCCCCCC", 4)
142 	|| base32touint8(buf, "BBBBBBBB", 5)
143 	|| base32touint8(buf, "ABCDEFGH", 5);
144 }
145 
test_decode_fail()146 static int test_decode_fail() {
147     uint8_t buf[256];
148     return !base32touint8(buf, "A", 1)
149 	|| !base32touint8(buf, "77", 2)
150 	|| !base32touint8(buf, "ABCDEFGH", 6);
151 }
152 
153 #define C(val) ((const uint8_t*)val)
test_misc_binary()154 static int test_misc_binary() {
155     return help_cmp_symmetric8("\\0", C("\0"), 1, "AA", 0)
156 	    + help_cmp_symmetric8("\\0\\0", C("\0\0"), 2, "AAAA", 0)
157 	    + help_cmp_symmetric8("\\xff", C("\xff"), 1, "74", 0)
158 	    + help_cmp_symmetric8("\\xff\\0\\xff", C("\xff\0\xff"), 3,
159 		    "74AP6", 0);
160 }
161 #undef C
162 
test_misc_binary64()163 static int test_misc_binary64() {
164     int ret = 0;
165     uint64_t buf[16];
166     buf[0] = _ULL(0x8b630e030ad09e5d);
167     buf[1] = _ULL(0x0e90fb246a3a75db);
168     buf[2] = _ULL(0xb6256c3ee7b8635a);
169     ret += help_cmp_symmetric64("test64:1", buf, 3,
170 	    "LWPNACQDBZRYXW3VHJVCJ64QBZNGHOHHHZWCLNQ", 0);
171     ++buf[2];
172     ret += help_cmp_symmetric64("test64:2", buf, 3,
173 	    "LWPNACQDBZRYXW3VHJVCJ64QBZNGHOHHHZWCLNQ", 1);
174     return ret;
175 }
176 
177 
178 TESTS(base32_test)
179     TEST(test_bidirectional_rfc4648);
180     TEST(test_not_bidirectional_rfc4648);
181     TEST(test_unidirectional_rfc4648);
182     TEST(test_decode_success);
183     TEST(test_decode_fail);
184     TEST(test_misc_binary);
185     TEST(test_misc_binary64);
186 ENDTESTS
187