1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
#include "testutils.h"
#include "base64.h"
#include "knuth-lfib.h"
static void
test_fuzz_once(struct base64_encode_ctx *encode,
struct base64_decode_ctx *decode,
size_t size, const uint8_t *input)
{
size_t base64_len = BASE64_ENCODE_RAW_LENGTH (size);
size_t out_len;
char *base64 = xalloc (base64_len + 2);
uint8_t *decoded = xalloc (size + 2);
*base64++ = 0x12;
base64[base64_len] = 0x34;
*decoded++ = 0x56;
decoded[size] = 0x78;
out_len = base64_encode_update(encode, base64, size, input);
ASSERT (out_len <= base64_len);
out_len += base64_encode_final(encode, base64 + out_len);
ASSERT (out_len == base64_len);
ASSERT (base64[-1] == 0x12);
ASSERT (base64[base64_len] == 0x34);
ASSERT(base64_decode_update(decode, &out_len, decoded,
base64_len, base64));
ASSERT(base64_decode_final(decode));
ASSERT (out_len == size);
ASSERT (decoded[-1] == 0x56);
ASSERT (decoded[size] == 0x78);
ASSERT(MEMEQ(size, input, decoded));
free (base64 - 1);
free (decoded - 1);
}
static void
test_fuzz(void)
{
/* Fuzz a round-trip through both encoder and decoder */
struct base64_encode_ctx encode;
struct base64_decode_ctx decode;
unsigned i;
size_t length;
uint8_t input[1024];
struct knuth_lfib_ctx rand_ctx;
knuth_lfib_init(&rand_ctx, 39854);
for (i = 0; i < 10000; i++)
{
length = i % sizeof(input);
/* length could be 0, which is fine we need to test that case too */
knuth_lfib_random(&rand_ctx, length, input);
base64_encode_init(&encode);
base64_decode_init(&decode);
test_fuzz_once(&encode, &decode, length, input);
base64url_encode_init(&encode);
base64url_decode_init(&decode);
test_fuzz_once(&encode, &decode, length, input);
}
}
static inline void
base64_encode_in_place (size_t length, uint8_t *data)
{
base64_encode_raw ((char *) data, length, data);
}
static inline int
base64_decode_in_place (struct base64_decode_ctx *ctx, size_t *dst_length,
size_t length, uint8_t *data)
{
return base64_decode_update (ctx, dst_length,
data, length, (const char *) data);
}
void
test_main(void)
{
ASSERT(BASE64_ENCODE_LENGTH(0) == 0); /* At most 4 bits */
ASSERT(BASE64_ENCODE_LENGTH(1) == 2); /* At most 12 bits */
ASSERT(BASE64_ENCODE_LENGTH(2) == 3); /* At most 20 bits */
ASSERT(BASE64_ENCODE_LENGTH(3) == 4); /* At most 28 bits */
ASSERT(BASE64_ENCODE_LENGTH(4) == 6); /* At most 36 bits */
ASSERT(BASE64_ENCODE_LENGTH(5) == 7); /* At most 44 bits */
ASSERT(BASE64_ENCODE_LENGTH(12) == 16); /* At most 100 bits */
ASSERT(BASE64_ENCODE_LENGTH(13) == 18); /* At most 108 bits */
ASSERT(BASE64_DECODE_LENGTH(0) == 0); /* At most 6 bits */
ASSERT(BASE64_DECODE_LENGTH(1) == 1); /* At most 12 bits */
ASSERT(BASE64_DECODE_LENGTH(2) == 2); /* At most 18 bits */
ASSERT(BASE64_DECODE_LENGTH(3) == 3); /* At most 24 bits */
ASSERT(BASE64_DECODE_LENGTH(4) == 3); /* At most 30 bits */
test_armor(&nettle_base64, LDATA(""), "");
test_armor(&nettle_base64, LDATA("H"), "SA==");
test_armor(&nettle_base64, LDATA("He"), "SGU=");
test_armor(&nettle_base64, LDATA("Hel"), "SGVs");
test_armor(&nettle_base64, LDATA("Hell"), "SGVsbA==");
test_armor(&nettle_base64, LDATA("Hello"), "SGVsbG8=");
test_armor(&nettle_base64, LDATA("Hello\0"), "SGVsbG8A");
test_armor(&nettle_base64, LDATA("Hello?>>>"), "SGVsbG8/Pj4+");
test_armor(&nettle_base64, LDATA("\xff\xff\xff\xff"), "/////w==");
test_armor(&nettle_base64url, LDATA(""), "");
test_armor(&nettle_base64url, LDATA("H"), "SA==");
test_armor(&nettle_base64url, LDATA("He"), "SGU=");
test_armor(&nettle_base64url, LDATA("Hel"), "SGVs");
test_armor(&nettle_base64url, LDATA("Hell"), "SGVsbA==");
test_armor(&nettle_base64url, LDATA("Hello"), "SGVsbG8=");
test_armor(&nettle_base64url, LDATA("Hello\0"), "SGVsbG8A");
test_armor(&nettle_base64url, LDATA("Hello?>>>"), "SGVsbG8_Pj4-");
test_armor(&nettle_base64url, LDATA("\xff\xff\xff\xff"), "_____w==");
{
/* Test overlapping areas */
uint8_t buffer[] = "Helloxxxx";
struct base64_decode_ctx ctx;
size_t dst_length;
ASSERT(BASE64_ENCODE_RAW_LENGTH(5) == 8);
base64_encode_in_place(5, buffer);
ASSERT(MEMEQ(9, buffer, "SGVsbG8=x"));
base64_decode_init(&ctx);
dst_length = 0; /* Output parameter only. */
ASSERT(base64_decode_in_place(&ctx, &dst_length, 8, buffer));
ASSERT(dst_length == 5);
ASSERT(MEMEQ(9, buffer, "HelloG8=x"));
}
test_fuzz ();
}
|