1 /*	$OpenBSD: base64test.c,v 1.10 2022/09/05 21:06:31 tb Exp $	*/
2 /*
3  * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <openssl/bio.h>
19 #include <openssl/evp.h>
20 
21 #include <err.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <sys/types.h>
25 
26 #define BUF_SIZE 128
27 
28 struct base64_test {
29 	const unsigned char in[BUF_SIZE];
30 	const ssize_t in_len;
31 	const unsigned char out[BUF_SIZE];
32 	const ssize_t out_len;
33 	const ssize_t valid_len;
34 };
35 
36 /*
37  * Many of these tests are based on those found in Go's encoding/base64 tests.
38  */
39 struct base64_test base64_tests[] = {
40 
41 	/* RFC3548 examples. */
42 	{ "\x14\xfb\x9c\x03\xd9\x7e", 6, "FPucA9l+", 8, 6, },
43 	{ "\x14\xfb\x9c\x03\xd9", 5, "FPucA9k=", 8, 5, },
44 	{ "\x14\xfb\x9c\x03", 4, "FPucAw==", 8, 4, },
45 
46 	/* RFC4648 examples. */
47 	{ "", 0, "", 0, 0, },
48 	{ "f", 1, "Zg==", 4, 1, },
49 	{ "fo", 2, "Zm8=", 4, 2, },
50 	{ "foo", 3, "Zm9v", 4, 3, },
51 	{ "foob", 4, "Zm9vYg==", 8, 4, },
52 	{ "fooba", 5, "Zm9vYmE=", 8, 5, },
53 	{ "foobar", 6, "Zm9vYmFy", 8, 6, },
54 
55 	/* Wikipedia examples. */
56 	{ "sure.", 5, "c3VyZS4=", 8, 5, },
57 	{ "sure", 4, "c3VyZQ==", 8, 4, },
58 	{ "sur", 3, "c3Vy", 4, 3, },
59 	{ "su", 2, "c3U=", 4, 2, },
60 	{ "leasure.", 8, "bGVhc3VyZS4=", 12, 8, },
61 	{ "easure.", 7, "ZWFzdXJlLg==", 12, 7, },
62 	{ "asure.", 6, "YXN1cmUu", 8, 6, },
63 
64 	{ "abcd", 4, "YWJjZA==", 8, 4, },
65 
66 	{
67 		"Twas brillig, and the slithy toves",
68 		34,
69 		"VHdhcyBicmlsbGlnLCBhbmQgdGhlIHNsaXRoeSB0b3Zlcw==",
70 		48,
71 		34,
72 	},
73 };
74 
75 #define N_TESTS (sizeof(base64_tests) / sizeof(*base64_tests))
76 
77 struct base64_test base64_nl_tests[] = {
78 
79 	/* Corrupt/invalid encodings. */
80 	{ "", -1, "", 0, 0, },
81 	{ "", -1, "!!!!", 4, 0, },
82 	{ "", -1, "====", 4, 0, },
83 	{ "", -1, "x===", 4, 0, },
84 	{ "", -1, "=AAA", 4, 0, },
85 	{ "", -1, "A=AA", 4, 0, },
86 	{ "", -1, "AA=A", 4, 0, },
87 	{ "", -1, "AA==A", 5, 0, },
88 	{ "", -1, "AAA=AAAA", 8, 0, },
89 	{ "", -1, "AAAAA", 5, 0, },
90 	{ "", -1, "AAAAAA", 6, 0, },
91 	{ "", -1, "A=", 2, 0, },
92 	{ "", -1, "A==", 3, 0, },
93 	{ "", -1, "AA=", 3, 0, },
94 	{ "", -1, "AA==", 4, 1, },		/* XXX - output ix 0x0. */
95 	{ "", -1, "AAA=", 4, 2, },		/* XXX - output ix 2x 0x0. */
96 	{ "", -1, "AAAA", 4, 3, },		/* XXX - output ix 3x 0x0. */
97 	{ "", -1, "AAAAAA=", 7, 0, },
98 	{ "", -1, "YWJjZA=====", 11, 0, },
99 
100 
101 	/* Encodings with embedded CR/LF. */
102 	{ "sure", 4, "c3VyZQ==", 8, 4, },
103 	{ "sure", 4, "c3VyZQ==\r", 9, 4, },
104 	{ "sure", 4, "c3VyZQ==\n", 9, 4, },
105 	{ "sure", 4, "c3VyZQ==\r\n", 10, 4, },
106 	{ "sure", 4, "c3VyZ\r\nQ==", 10, 4, },
107 	{ "sure", 4, "c3V\ryZ\nQ==", 10, 4, },
108 	{ "sure", 4, "c3V\nyZ\rQ==", 10, 4, },
109 	{ "sure", 4, "c3VyZ\nQ==", 9, 4, },
110 	{ "sure", 4, "c3VyZQ\n==", 9, 4, },
111 	{ "sure", 4, "c3VyZQ=\n=", 9, 4, },
112 	{ "sure", 4, "c3VyZQ=\r\n\r\n=", 12, 4, },
113 
114 	{
115 		"",
116 		-1,
117 		"YWJjZA======================================================"
118 		"============",
119 		74,
120 		0,
121 	},
122 
123 	/* OpenSSL-1.1.1d test */
124 	/* canonical */
125 	{ "", 0, "", 0, 0, },
126 	/* canonical */
127 	{ "h", 1, "aA==\n", 5, 1, },
128 	/* canonical */
129 	{ "hello", 5, "aGVsbG8=\n", 9, 5, },
130 	/* canonical */
131 	{ "hello world!", 12, "aGVsbG8gd29ybGQh\n", 17, 12, },
132 	/* canonical */
133 	{ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\xa0\xb0\xc0\xd0\xe0\xf0\x00", 17, "AAECAwQFBgcICaCwwNDg8AA=\n", 25, 17, },
134 	/* invalid # Missing padding */
135 	{ "", -1, "aGVsbG8", 7, 0, },
136 	/* invalid */
137 	{ "", -1, "aGVsbG8\n", 8, 0, },
138 	/* valid # Tolerate missing newline */
139 	{ "hello", -1, "aGVsbG8=", 8, 5, },
140 	/* invalid # Don't tolerate extra trailing '=' */
141 	{ "", -1, "aGVsbG8==\n", 10, 0, },
142 	/* invalid */
143 	{ "", -1, "aGVsbG8===\n", 11, 0, },
144 	/* invalid # Don't tolerate data after '=' */
145 	{ "", -1, "aGV=sbG8=\n", 10, 0, },
146 	/* valid # Newlines are ignored */
147 	{ "hello", -1, "aGV\nsbG8=\n", 10, 5, },
148 	/* canonical */
149 	{ "hello", 5, "\x61\x47\x56\x73\x62\x47\x38\x3d\x0a", 9, 5, },
150 	/* invalid # Invalid characters */
151 	{ "", -1, "\x61\x47\x56\x73\x62\x47\x38\x3d\x0a\x00", 10, 0, },
152 	/* invalid */
153 	{ "", -1, "\x61\x47\x56\x00\x73\x62\x47\x38\x3d\x0a", 10, 0, },
154 	/* invalid */
155 	{ "", -1, "\x61\x47\x56\x01\x73\x62\x47\x38\x3d\x0a", 10, 0, },
156 	/* invalid */
157 	{ "", -1, "\x61\x47\x56\x80\x73\x62\x47\x38\x3d\x0a", 10, 0, },
158 	/* invalid */
159 	{ "", -1, "\xe1\x47\x56\x73\x62\x47\x38\x3d\x0a", 9, 0, },
160 	/* canonical */
161 	{ "OpenSSLOpenSSL\n", 15, "T3BlblNTTE9wZW5TU0wK\n", 21, 15, },
162 	/* valid */
163 	{ "OpenSSLOpenSSL\n", -1, "T3BlblNTTE9wZW5TU0wK", 20, 15, },
164 	/* invalid # Truncate 1-3 chars */
165 	{ "", -1, "T3BlblNTTE9wZW5TU0w", 19, 0, },
166 	/* invalid */
167 	{ "", -1, "T3BlblNTTE9wZW5TU0", 18, 0, },
168 	/* invalid */
169 	{ "", -1, "T3BlblNTTE9wZW5TU", 17, 0, },
170 	/* invalid */
171 	{ "", -1, "T3BlblNTTE9wZW5TU0wK====", 24, 0, },
172 	/* invalid */
173 	{ "", -1, "T3BlblNTTE9wZW5TU0wK============================================\n", 65, 0, },
174 	/* invalid */
175 	{ "", -1, "YQ==YQ==YQ==\n", 13, 0, },
176 	/* invalid */
177 	{ "", -1, "A", 1, 0, },
178 	/* invalid */
179 	{ "", -1, "A\n", 2, 0, },
180 	/* invalid */
181 	{ "", -1, "A=", 2, 0, },
182 	/* invalid */
183 	{ "", -1, "A==\n", 4, 0, },
184 	/* invalid */
185 	{ "", -1, "A===\n", 5, 0, },
186 	/* invalid */
187 	{ "", -1, "A====\n", 6, 0, },
188 	/* valid */
189 	{ "OpenSSLOpenSSL\n", -1, "T3BlblNTTE9wZW5TU0wK\n\n", 22, 15, },
190 	/* valid */
191 	{ "OpenSSLOpenSSL\n", -1, "T3BlblNTTE\n9wZW5TU0wK", 21, 15, },
192 	/* invalid # CVE 2015-0292 */
193 	{ "", -1, "ZW5jb2RlIG1lCg==================================================================\n", 81, 0, },
194 	/* canonical */
195 	{ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 46, "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA==\n", 65, 46, },
196 	/* valid */
197 	{ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", -1, "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA\n==\n", 66, 46, },
198 	/* valid */
199 	{ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", -1, "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA=\n=\n", 66, 46, },
200 	/* invalid */
201 	{ "", -1, "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA====\n", 67, 0, },
202 	/* canonical # Multiline output without padding */
203 	{ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 60, "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4\neHh4eHh4eHh4eHh4\n", 82, 60, },
204 	/* canonical # Multiline output with padding */
205 	{ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 64, "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4\neHh4eHh4eHh4eHh4eHh4eA==\n", 90, 64, },
206 	/* valid # Multiline output with line break in the middle of a b64 block is accepted */
207 	{ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", -1, "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh\n4eHh4eHh4eHh4eHh4eHh4eA==\n", 90, 64, },
208 	/* valid # Long lines are accepted */
209 	{ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", -1, "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA==\n", 89, 64, },
210 	/* invalid # Multiline input with data after '='. */
211 	{ "", -1, "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA==\neHh4eHh4eHh4eHh4eHh4eHh4\n", 90, 0, },
212 	/* invalid */
213 	{ "", -1, "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4\neA==eHh4eHh4eHh4eHh4eHh4\n", 90, 0, },
214 	/* valid # B64_EOF ('-') terminates input and trailing bytes are ignored */
215 	{ "OpenSSLOpenSSL\n", -1, "T3BlblNTTE9wZW5TU0wK\n-abcd", 26, 15, },
216 	/* valid */
217 	{ "OpenSSLOpenSSL\n", -1, "T3BlblNTTE9wZW5TU0wK-abcd", 25, 15, },
218 };
219 
220 #define N_NL_TESTS (sizeof(base64_nl_tests) / sizeof(*base64_nl_tests))
221 
222 struct base64_test base64_no_nl_tests[] = {
223 
224 	/*
225 	 * In non-newline mode, the output resulting from corrupt/invalid
226 	 * encodings is completely crazy. A number of zero bytes is returned
227 	 * rather than nothing.
228 	 */
229 
230 	/* Corrupt/invalid encodings. */
231 	{ "", -1, "", 0, 0, },
232 	{ "", -1, "!!!!", 4, 0, },
233 	{ "", -1, "====", 4, 1, },
234 	{ "", -1, "x===", 4, 1, },
235 	{ "", -1, "=AAA", 4, 3, },
236 	{ "", -1, "A=AA", 4, 3, },
237 	{ "", -1, "AA=A", 4, 3, },
238 	{ "", -1, "AA==A", 5, 1, },
239 	{ "", -1, "AAA=AAAA", 8, 6, },
240 	{ "", -1, "AAAAA", 5, 3, },
241 	{ "", -1, "AAAAAA", 6, 3, },
242 	{ "", -1, "A=", 2, 0, },
243 	{ "", -1, "A==", 3, 0, },
244 	{ "", -1, "AA=", 3, 0, },
245 	{ "", -1, "AA==", 4, 1, },
246 	{ "", -1, "AAA=", 4, 2, },
247 	{ "", -1, "AAAA", 4, 3, },
248 	{ "", -1, "AAAAAA=", 7, 3, },
249 	{ "", -1, "YWJjZA=====", 11, 4, },
250 
251 	/* Encodings with embedded CR/LF. */
252 	{ "sure", 4, "c3VyZQ==", 8, 4, },
253 	{ "sure", 4, "c3VyZQ==\r", 9, 4, },
254 	{ "sure", 4, "c3VyZQ==\n", 9, 4, },
255 	{ "sure", 4, "c3VyZQ==\r\n", 10, 4, },
256 	{ "sure", -1, "c3VyZ\r\nQ==", 10, 0, },
257 	{ "sure", -1, "c3V\ryZ\nQ==", 10, 0, },
258 	{ "sure", -1, "c3V\nyZ\rQ==", 10, 0, },
259 	{ "sure", -1, "c3VyZ\nQ==", 9, 0, },
260 	{ "sure", -1, "c3VyZQ\n==", 9, 0, },
261 	{ "sure", -1, "c3VyZQ=\n=", 9, 0, },
262 	{ "sure", -1, "c3VyZQ=\r\n\r\n=", 12, 0, },
263 
264 	/*
265 	 * This is invalid, yet results in 'abcd' followed by a stream of
266 	 * zero value bytes.
267 	 */
268 	{
269 		"",
270 		-1,
271 		"YWJjZA======================================================"
272 		"============",
273 		74,
274 		52,
275 	},
276 };
277 
278 #define N_NO_NL_TESTS (sizeof(base64_no_nl_tests) / sizeof(*base64_no_nl_tests))
279 
280 static int
281 base64_encoding_test(int test_no, struct base64_test *bt, int test_nl)
282 {
283 	BIO *bio_b64, *bio_mem;
284 	unsigned char *buf, *out;
285 	ssize_t i, len, b64len;
286 	int failure = 0;
287 
288 	buf = malloc(BUF_SIZE);
289 	if (buf == NULL)
290 		errx(1, "malloc");
291 
292 	bio_b64 = BIO_new(BIO_f_base64());
293 	if (bio_b64 == NULL)
294 		errx(1, "BIO_new failed for BIO_f_base64");
295 
296 	bio_mem = BIO_new(BIO_s_mem());
297 	if (bio_mem == NULL)
298 		errx(1, "BIO_new failed for BIO_s_mem");
299 
300 	bio_mem = BIO_push(bio_b64, bio_mem);
301 
302 	if (!test_nl)
303 		BIO_set_flags(bio_b64, BIO_FLAGS_BASE64_NO_NL);
304 
305 	len = BIO_write(bio_mem, bt->in, bt->in_len);
306 	if (len != bt->in_len) {
307 		fprintf(stderr, "FAIL: test %d - only wrote %zd out of %zd "
308 		    "characters\n", test_no, len, bt->in_len);
309 		failure = 1;
310 		goto done;
311 	}
312 	if (BIO_flush(bio_mem) < 0) {
313 		fprintf(stderr, "FAIL: test %d - flush failed\n", test_no);
314 		failure = 1;
315 		goto done;
316 	}
317 
318 	b64len = 0;
319 	for (i = 0; i < bt->out_len; i++) {
320 		if ((!test_nl ||
321 		    (test_nl && (i % 64 != 0 || i == bt->out_len - 1))) &&
322 		    (bt->out[i] == '\r' || bt->out[i] == '\n'))
323 			continue;
324 		buf[b64len++] = bt->out[i];
325 	}
326 	if (test_nl)
327 		buf[b64len++] = '\n';
328 
329 	len = BIO_get_mem_data(bio_mem, &out);
330 
331 	/* An empty string with NL results in no output, rather than '\n'. */
332 	if (test_nl && b64len == 1 && len == 0)
333 		goto done;
334 
335 	if (len != b64len) {
336 		fprintf(stderr, "FAIL: test %d - encoding resulted in %zd "
337 		    "characters instead of %zd\n", test_no, len, b64len);
338 		failure = 1;
339 		goto done;
340 	}
341 
342 	if (memcmp(buf, out, b64len) != 0) {
343 		fprintf(stderr, "FAIL: test %d - encoding differs:\n", test_no);
344 		fprintf(stderr, "  encoding: ");
345 		for (i = 0; i < len; i++)
346 			fprintf(stderr, "%c", out[i]);
347 		fprintf(stderr, "\n");
348 		fprintf(stderr, " test data: ");
349 		for (i = 0; i < bt->out_len; i++)
350 			fprintf(stderr, "%c", buf[i]);
351 		fprintf(stderr, "\n");
352 		failure = 1;
353 	}
354 
355 done:
356 	BIO_free_all(bio_mem);
357 	free(buf);
358 
359 	return failure;
360 }
361 
362 static int
363 base64_decoding_test(int test_no, struct base64_test *bt, int test_nl)
364 {
365 	BIO *bio_b64, *bio_mem;
366 	char *buf, *input;
367 	ssize_t i, inlen, len;
368 	int failure = 0;
369 
370 	buf = malloc(BUF_SIZE);
371 	if (buf == NULL)
372 		errx(1, "malloc");
373 
374 	if ((input = malloc(BUF_SIZE)) == NULL)
375 		errx(1, "malloc");
376 
377 	memcpy(input, bt->out, bt->out_len);
378 	inlen = bt->out_len;
379 	if (test_nl) {
380 		memcpy(&input[bt->out_len], "\r\n", 2);
381 		inlen += 2;
382 	}
383 
384 	bio_mem = BIO_new_mem_buf(input, inlen);
385 	if (bio_mem == NULL)
386 		errx(1, "BIO_new_mem_buf failed");
387 
388 	bio_b64 = BIO_new(BIO_f_base64());
389 	if (bio_b64 == NULL)
390 		errx(1, "BIO_new failed for BIO_f_base64");
391 
392 	if (!test_nl)
393 		BIO_set_flags(bio_b64, BIO_FLAGS_BASE64_NO_NL);
394 
395 	bio_mem = BIO_push(bio_b64, bio_mem);
396 
397 	/*
398 	 * If we wrote zero characters then a BIO_read will result in a return
399 	 * value of -1, hence we need to handle this case.
400 	 */
401 	len = BIO_read(bio_mem, buf, BUF_SIZE);
402 	if (len != bt->valid_len && (bt->in_len != 0 || len != -1)) {
403 		fprintf(stderr, "FAIL: test %d - decoding resulted in %zd "
404 		    "characters instead of %zd\n", test_no, len, bt->valid_len);
405 		fprintf(stderr, "  input: ");
406 		for (i = 0; i < inlen; i++)
407 			fprintf(stderr, "%c", input[i]);
408 		fprintf(stderr, "\n");
409 		fprintf(stderr, "  decoding: ");
410 		for (i = 0; i < len; i++)
411 			fprintf(stderr, "0x%x ", buf[i]);
412 		fprintf(stderr, "\n");
413 		failure = 1;
414 		goto done;
415 	}
416 
417 	/* See if we expect this to fail decoding. */
418 	if (bt->in_len == -1)
419 		goto done;
420 
421 	if (memcmp(bt->in, buf, bt->in_len) != 0) {
422 		fprintf(stderr, "FAIL: test %d - decoding differs:\n", test_no);
423 		fprintf(stderr, "  decoding: ");
424 		for (i = 0; i < len; i++)
425 			fprintf(stderr, "0x%x ", buf[i]);
426 		fprintf(stderr, "\n");
427 		fprintf(stderr, " test data: ");
428 		for (i = 0; i < bt->in_len; i++)
429 			fprintf(stderr, "0x%x ", bt->in[i]);
430 		fprintf(stderr, "\n");
431 		failure = 1;
432 	}
433 
434 done:
435 	BIO_free_all(bio_mem);
436 	free(buf);
437 	free(input);
438 
439 	return failure;
440 }
441 
442 int
443 main(int argc, char **argv)
444 {
445 	struct base64_test *bt;
446 	int failed = 0;
447 	size_t i;
448 
449 	fprintf(stderr, "Starting combined tests...\n");
450 
451 	for (i = 0; i < N_TESTS; i++) {
452 		bt = &base64_tests[i];
453 		if (bt->in_len != -1)
454 			failed += base64_encoding_test(i, bt, 0);
455 		if (bt->out_len != -1)
456 			failed += base64_decoding_test(i, bt, 0);
457 		if (bt->in_len != -1)
458 			failed += base64_encoding_test(i, bt, 1);
459 		if (bt->out_len != -1)
460 			failed += base64_decoding_test(i, bt, 1);
461 	}
462 
463 	fprintf(stderr, "Starting NL tests...\n");
464 
465 	for (i = 0; i < N_NL_TESTS; i++) {
466 		bt = &base64_nl_tests[i];
467 
468 		if (bt->in_len != -1)
469 			failed += base64_encoding_test(i, bt, 1);
470 		if (bt->out_len != -1)
471 			failed += base64_decoding_test(i, bt, 1);
472 	}
473 
474 	fprintf(stderr, "Starting NO NL tests...\n");
475 
476 	for (i = 0; i < N_NO_NL_TESTS; i++) {
477 		bt = &base64_no_nl_tests[i];
478 
479 		if (bt->in_len != -1)
480 			failed += base64_encoding_test(i, bt, 0);
481 		if (bt->out_len != -1)
482 			failed += base64_decoding_test(i, bt, 0);
483 	}
484 
485 	return failed;
486 }
487