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); } }
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_raw(buffer, 5, buffer); ASSERT(MEMEQ(9, buffer, "SGVsbG8=x")); base64_decode_init(&ctx); dst_length = 0; /* Output parameter only. */ ASSERT(base64_decode_update(&ctx, &dst_length, buffer, 8, buffer)); ASSERT(dst_length == 5); ASSERT(MEMEQ(9, buffer, "HelloG8=x")); } test_fuzz (); }
stl_string base64_decode (const char *line) { stl_string ret; unsigned len = strlen (line); char *res = (char *)malloc (len); struct base64_decode_ctx str; base64_decode_init (&str); base64_decode_update (&str, &len, (uint8_t*)res, len, (uint8_t*)line); base64_decode_final (&str); ret.append (res, len); free (res); return ret; }
getdns_return_t _getdns_decode_base64(const char* str, uint8_t* res, size_t res_size) { struct base64_decode_ctx ctx; uint8_t* lim = res + res_size; base64_decode_init(&ctx); for(; *str != '\0' && res < lim; ++str) { int r = base64_decode_single(&ctx, res, *str); if (r == -1 ) return GETDNS_RETURN_GENERIC_ERROR; res += r; } return (res == lim) ? GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR; }
static size_t base64_decode_raw(const uint8_t *src, size_t src_len, uint8_t *dst, size_t dst_max_size) { assert(src); assert(dst); struct base64_decode_ctx ctx; base64_decode_init(&ctx); nettle_len dst_size = dst_max_size; int result = nettle_base64_decode_update(&ctx, &dst_size, dst, src_len, src); if (result != 1) { return 0; } return dst_size; }
/* decodes data and puts the result into result (locally allocated) * The result_size is the return value */ int _gnutls_base64_decode(const uint8_t * data, size_t data_size, gnutls_datum_t * result) { int ret; size_t size; gnutls_datum_t pdata; struct base64_decode_ctx ctx; ret = cpydata(data, data_size, &pdata); if (ret < 0) { gnutls_assert(); return ret; } base64_decode_init(&ctx); size = BASE64_DECODE_LENGTH(data_size); result->data = gnutls_malloc(size); if (result->data == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); ret = base64_decode_update(&ctx, &size, result->data, pdata.size, pdata.data); if (ret == 0) { gnutls_assert(); gnutls_free(result->data); result->data = NULL; ret = GNUTLS_E_PARSING_ERROR; goto cleanup; } ret = base64_decode_final(&ctx); if (ret != 1) return gnutls_assert_val(GNUTLS_E_PARSING_ERROR); result->size = size; ret = size; cleanup: gnutls_free(pdata.data); return ret; }
// Convert string to uint8 array; return outsize size_t str_to_uint8(unsigned char *in, uint8_t *out, size_t insize) { int errU; //update error int errF; //final error size_t outsize; //outgoing decoded bytes struct base64_decode_ctx decoder; //nettle decoder base64_decode_init(&decoder); //init decoder errU = base64_decode_update(&decoder, &outsize, out, insize, in); //decode errF = base64_decode_final(&decoder); //check padding size if (errU == 0) //throw b64 errors err(ERR_B64, "Decode update error"); if (errF == 0) err(ERR_B64, "Decode final error"); return outsize; //return number of bytes written to out }
static int decode_base64(struct nettle_buffer *buffer, unsigned start, unsigned *length) { struct base64_decode_ctx ctx; base64_decode_init(&ctx); /* Decode in place */ if (base64_decode_update(&ctx, length, buffer->contents + start, *length, buffer->contents + start) && base64_decode_final(&ctx)) return 1; else { werror("Invalid base64 date.\n"); return 0; } }
/* NOTE: Decodes the input string in place */ int sexp_transport_iterator_first(struct sexp_iterator *iterator, unsigned length, uint8_t *input) { /* We first base64 decode any transport encoded sexp at the start of * the input. */ unsigned in = 0; unsigned out = 0; while (in < length) switch(input[in]) { case ' ': /* SPC, TAB, LF, CR */ case '\t': case '\n': case '\r': in++; break; case ';': /* Comments */ while (++in < length && input[in] != '\n') ; break; case '{': { /* Found transport encoding */ struct base64_decode_ctx ctx; unsigned coded_length; unsigned end; for (end = ++in; end < length && input[end] != '}'; end++) ; if (end == length) return 0; base64_decode_init(&ctx); coded_length = end - in; if (base64_decode_update(&ctx, &coded_length, input + out, coded_length, input + in) && base64_decode_final(&ctx)) { out += coded_length; in = end + 1; } else return 0; break; } default: /* Expression isn't in transport encoding. Rest of the input * should be in canonical encoding. */ goto transport_done; } transport_done: /* Here, we have two, possibly empty, input parts in canonical * encoding: * * 0...out-1, in...length -1 * * If the input was already in canonical encoding, out = 0 and in = * amount of leading space. * * If all input was in transport encoding, in == length. */ if (!out) { input += in; length -= in; } else if (in == length) length = out; else if (out == in) /* Unusual case, nothing happens */ ; else { /* Both parts non-empty */ assert(out < in); memmove(input + out, input + in, length - in); length -= (in - out); } return sexp_iterator_first(iterator, length, input); }