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