diff options
author | lloyd <[email protected]> | 2011-05-16 16:28:54 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2011-05-16 16:28:54 +0000 |
commit | 3c0e96e6555b0e658684e55f4c23ca21fd6f3a19 (patch) | |
tree | 732cb39ec0c6647d35395ef1890c3d212c7c9258 | |
parent | 9e8743ee1d84eb196628ad687b9a87da5d2663a2 (diff) |
Fixes for base64 incremental decoding.
Define the Base64_Decoder filter in terms of base64_decode
Don't use locked memory in the hex or base64 filters.
-rw-r--r-- | src/codec/base64/base64.cpp | 25 | ||||
-rw-r--r-- | src/filters/codec_filt/b64_filt.cpp | 137 | ||||
-rw-r--r-- | src/filters/codec_filt/b64_filt.h | 10 | ||||
-rw-r--r-- | src/filters/codec_filt/hex_filt.h | 4 |
4 files changed, 54 insertions, 122 deletions
diff --git a/src/codec/base64/base64.cpp b/src/codec/base64/base64.cpp index 27e6853bd..4e3a84dc7 100644 --- a/src/codec/base64/base64.cpp +++ b/src/codec/base64/base64.cpp @@ -140,7 +140,6 @@ size_t base64_decode(byte output[], byte decode_buf[4]; size_t decode_buf_pos = 0; size_t final_truncate = 0; - bool seen_pad = false; clear_mem(output, input_length * 3 / 4); @@ -148,19 +147,13 @@ size_t base64_decode(byte output[], { const byte bin = BASE64_TO_BIN[static_cast<byte>(input[i])]; - if(seen_pad && bin != 0x81) - throw std::invalid_argument("base64_decode: invalid padding"); - if(bin <= 0x3F) { decode_buf[decode_buf_pos] = bin; decode_buf_pos += 1; } - else if(!(final_inputs && bin == 0x81)) + else if(!(bin == 0x81 || (bin == 0x80 && ignore_ws))) { - if(bin == 0x80 && ignore_ws) - continue; - std::string bad_char(1, input[i]); if(bad_char == "\t") bad_char = "\\t"; @@ -173,12 +166,10 @@ size_t base64_decode(byte output[], } /* - * If we either see a pad character, or we are the the end - * of the input + * If we're at the end of the input, pad with 0s and truncate */ - if(final_inputs && (bin == 0x81 || i == input_length - 1)) + if(final_inputs && (i == input_length - 1)) { - seen_pad = true; if(decode_buf_pos) { for(size_t i = decode_buf_pos; i != 4; ++i) @@ -196,10 +187,16 @@ size_t base64_decode(byte output[], out_ptr += 3; decode_buf_pos = 0; + input_consumed = i+1; } } - input_consumed = input_length - decode_buf_pos; + while(input_consumed < input_length && + BASE64_TO_BIN[static_cast<byte>(input[input_consumed])] == 0x80) + { + ++input_consumed; + } + size_t written = (out_ptr - output) - final_truncate; return written; @@ -231,7 +228,7 @@ SecureVector<byte> base64_decode(const char input[], size_t input_length, bool ignore_ws) { - SecureVector<byte> bin(1 + (input_length * 3) / 4); + SecureVector<byte> bin((round_up<size_t>(input_length, 4) * 3) / 4); size_t written = base64_decode(&bin[0], input, diff --git a/src/filters/codec_filt/b64_filt.cpp b/src/filters/codec_filt/b64_filt.cpp index 8a90f8b5f..9341571d4 100644 --- a/src/filters/codec_filt/b64_filt.cpp +++ b/src/filters/codec_filt/b64_filt.cpp @@ -14,32 +14,6 @@ namespace Botan { /* -* Base64 Decoder Lookup Table -* Warning: assumes ASCII encodings -*/ -static const byte BASE64_TO_BIN[256] = { -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x3E, 0x80, 0x80, 0x80, 0x3F, 0x34, 0x35, 0x36, 0x37, -0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, -0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, -0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, -0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }; - -/* * Base64_Encoder Constructor */ Base64_Encoder::Base64_Encoder(bool breaks, size_t length, bool t_n) : @@ -68,6 +42,7 @@ void Base64_Encoder::encode_and_send(const byte input[], size_t length, do_output(&out[0], produced); + // FIXME: s/proc/consumed/? input += proc; length -= proc; } @@ -138,58 +113,9 @@ void Base64_Encoder::end_msg() /* * Base64_Decoder Constructor */ -Base64_Decoder::Base64_Decoder(Decoder_Checking c) : checking(c) - { - in.resize(48); - out.resize(3); - position = 0; - } - -/* -* Check if a character is a valid Base64 char -*/ -bool Base64_Decoder::is_valid(byte in) - { - return (BASE64_TO_BIN[in] != 0x80); - } - -/* -* Base64 Decoding Operation -*/ -void Base64_Decoder::decode(const byte in[4], byte out[3]) - { - out[0] = ((BASE64_TO_BIN[in[0]] << 2) | (BASE64_TO_BIN[in[1]] >> 4)); - out[1] = ((BASE64_TO_BIN[in[1]] << 4) | (BASE64_TO_BIN[in[2]] >> 2)); - out[2] = ((BASE64_TO_BIN[in[2]] << 6) | (BASE64_TO_BIN[in[3]])); - } - -/* -* Decode and send a block -*/ -void Base64_Decoder::decode_and_send(const byte block[], size_t length) - { - for(size_t i = 0; i != length; i += 4) - { - decode(block + i, &out[0]); - send(out, 3); - } - } - -/* -* Handle processing an invalid character -*/ -void Base64_Decoder::handle_bad_char(byte c) +Base64_Decoder::Base64_Decoder(Decoder_Checking c) : + checking(c), in(64), out(48), position(0) { - if(c == '=' || checking == NONE) - return; - - if((checking == IGNORE_WS) && Charset::is_space(c)) - return; - - throw Decoding_Error( - std::string("Base64_Decoder: Invalid base64 character '") + - static_cast<char>(c) + "'" - ); } /* @@ -197,18 +123,32 @@ void Base64_Decoder::handle_bad_char(byte c) */ void Base64_Decoder::write(const byte input[], size_t length) { - for(size_t i = 0; i != length; ++i) + while(length) { - if(is_valid(input[i])) - in[position++] = input[i]; - else - handle_bad_char(input[i]); + size_t to_copy = std::min<size_t>(length, in.size() - position); + copy_mem(&in[position], input, to_copy); + position += to_copy; + + size_t consumed = 0; + size_t written = base64_decode(&out[0], + reinterpret_cast<const char*>(&in[0]), + position, + consumed, + false, + checking != FULL_CHECK); + + send(out, written); - if(position == in.size()) + if(consumed != position) { - decode_and_send(&in[0], in.size()); - position = 0; + copy_mem(&in[0], &in[consumed], position - consumed); + position = position - consumed; } + else + position = 0; + + length -= to_copy; + input += to_copy; } } @@ -217,21 +157,22 @@ void Base64_Decoder::write(const byte input[], size_t length) */ void Base64_Decoder::end_msg() { - if(position != 0) - { - size_t start_of_last_block = 4 * (position / 4), - left_over = position % 4; - decode_and_send(&in[0], start_of_last_block); + size_t consumed = 0; + size_t written = base64_decode(&out[0], + reinterpret_cast<const char*>(&in[0]), + position, + consumed, + true, + checking != FULL_CHECK); + + send(out, written); + + const bool not_full_bytes = consumed != position; - if(left_over) - { - SecureVector<byte> remainder(4); - copy_mem(&remainder[0], &in[start_of_last_block], left_over); - decode(&remainder[0], &out[0]); - send(out, ((left_over == 1) ? (1) : (left_over - 1))); - } - } position = 0; + + if(not_full_bytes) + throw std::invalid_argument("Base64_Decoder: Input not full bytes"); } } diff --git a/src/filters/codec_filt/b64_filt.h b/src/filters/codec_filt/b64_filt.h index df3896666..afff53f30 100644 --- a/src/filters/codec_filt/b64_filt.h +++ b/src/filters/codec_filt/b64_filt.h @@ -47,7 +47,7 @@ class BOTAN_DLL Base64_Encoder : public Filter const size_t line_length; const bool trailing_newline; - SecureVector<byte> in, out; + MemoryVector<byte> in, out; size_t position, out_position; }; @@ -78,14 +78,8 @@ class BOTAN_DLL Base64_Decoder : public Filter */ Base64_Decoder(Decoder_Checking checking = NONE); private: - static void decode(const byte input[4], byte output[3]); - static bool is_valid(byte c); - - void decode_and_send(const byte[], size_t); - void handle_bad_char(byte); - const Decoder_Checking checking; - SecureVector<byte> in, out; + MemoryVector<byte> in, out; size_t position; }; diff --git a/src/filters/codec_filt/hex_filt.h b/src/filters/codec_filt/hex_filt.h index cfbb818d3..0dc38c804 100644 --- a/src/filters/codec_filt/hex_filt.h +++ b/src/filters/codec_filt/hex_filt.h @@ -49,7 +49,7 @@ class BOTAN_DLL Hex_Encoder : public Filter const Case casing; const size_t line_length; - SecureVector<byte> in, out; + MemoryVector<byte> in, out; size_t position, counter; }; @@ -72,7 +72,7 @@ class BOTAN_DLL Hex_Decoder : public Filter Hex_Decoder(Decoder_Checking checking = NONE); private: const Decoder_Checking checking; - SecureVector<byte> in, out; + MemoryVector<byte> in, out; size_t position; }; |