aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2011-05-16 16:28:54 +0000
committerlloyd <[email protected]>2011-05-16 16:28:54 +0000
commit3c0e96e6555b0e658684e55f4c23ca21fd6f3a19 (patch)
tree732cb39ec0c6647d35395ef1890c3d212c7c9258
parent9e8743ee1d84eb196628ad687b9a87da5d2663a2 (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.cpp25
-rw-r--r--src/filters/codec_filt/b64_filt.cpp137
-rw-r--r--src/filters/codec_filt/b64_filt.h10
-rw-r--r--src/filters/codec_filt/hex_filt.h4
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;
};