aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/codec/hex/hex.cpp180
-rw-r--r--src/codec/hex/hex.h108
-rw-r--r--src/codec/hex/info.txt1
-rw-r--r--src/filters/filters.h4
-rw-r--r--src/filters/hex/hex_char.cpp48
-rw-r--r--src/filters/hex_filt/hex_filt.cpp (renamed from src/filters/hex/hex.cpp)104
-rw-r--r--src/filters/hex_filt/hex_filt.h (renamed from src/filters/hex/hex.h)24
-rw-r--r--src/filters/hex_filt/info.txt (renamed from src/filters/hex/info.txt)2
8 files changed, 334 insertions, 137 deletions
diff --git a/src/codec/hex/hex.cpp b/src/codec/hex/hex.cpp
new file mode 100644
index 000000000..70e819906
--- /dev/null
+++ b/src/codec/hex/hex.cpp
@@ -0,0 +1,180 @@
+/*
+* Hex Encoding and Decoding
+* (C) 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/hex.h>
+#include <botan/mem_ops.h>
+#include <stdexcept>
+
+namespace Botan {
+
+void hex_encode(char output[],
+ const byte input[],
+ u32bit input_length,
+ bool uppercase)
+ {
+ static const byte BIN_TO_HEX_UPPER[16] = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F' };
+
+ static const byte BIN_TO_HEX_LOWER[16] = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f' };
+
+ const byte* tbl = uppercase ? BIN_TO_HEX_UPPER : BIN_TO_HEX_LOWER;
+
+ for(u32bit i = 0; i != input_length; ++i)
+ {
+ byte x = input[i];
+ output[2*i ] = tbl[(x >> 4) & 0x0F];
+ output[2*i+1] = tbl[(x ) & 0x0F];
+ }
+ }
+
+std::string hex_encode(const byte input[],
+ u32bit input_length,
+ bool uppercase)
+ {
+ std::string output(2 * input_length, 0);
+ hex_encode(&output[0], input, input_length, uppercase);
+ return output;
+ }
+
+u32bit hex_decode(byte output[],
+ const char input[],
+ u32bit input_length,
+ u32bit& input_consumed,
+ bool ignore_ws)
+ {
+ /*
+ * Mapping of hex characters to either their binary equivalent
+ * or to an error code.
+ * If valid hex (0-9 A-F a-f), the value.
+ * If whitespace, then 0x80
+ * Otherwise 0xFF
+ * Warning: this table assumes ASCII character encodings
+ */
+
+ static const byte HEX_TO_BIN[256] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80,
+ 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01,
+ 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
+ 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+
+ byte* out_ptr = output;
+ bool top_nibble = true;
+
+ clear_mem(output, input_length / 2);
+
+ for(u32bit i = 0; i != input_length; ++i)
+ {
+ const byte bin = HEX_TO_BIN[(byte)input[i]];
+
+ if(bin >= 0x10)
+ {
+ if(bin == 0x80 && ignore_ws)
+ continue;
+
+ std::string bad_char(1, input[i]);
+ if(bad_char == "\t")
+ bad_char = "\\t";
+ else if(bad_char == "\n")
+ bad_char = "\\n";
+
+ throw std::invalid_argument(
+ std::string("hex_decode: invalid hex character '") +
+ bad_char + "'");
+ }
+
+ *out_ptr |= bin << (top_nibble*4);
+
+ top_nibble = !top_nibble;
+ if(top_nibble)
+ ++out_ptr;
+ }
+
+ input_consumed = input_length;
+ u32bit written = (out_ptr - output);
+
+ /*
+ * We only got half of a byte at the end; zap the half-written
+ * output and mark it as unread
+ */
+ if(!top_nibble)
+ {
+ *out_ptr = 0;
+ input_consumed -= 1;
+ }
+
+ return written;
+ }
+
+u32bit hex_decode(byte output[],
+ const char input[],
+ u32bit input_length,
+ bool ignore_ws)
+ {
+ u32bit consumed = 0;
+ u32bit written = hex_decode(output, input, input_length,
+ consumed, ignore_ws);
+
+ if(consumed != input_length)
+ throw std::invalid_argument("hex_decode: input did not have full bytes");
+
+ return written;
+ }
+
+u32bit hex_decode(byte output[],
+ const std::string& input,
+ bool ignore_ws)
+ {
+ return hex_decode(output, &input[0], input.length(), ignore_ws);
+ }
+
+SecureVector<byte> hex_decode(const char input[],
+ u32bit input_length,
+ bool ignore_ws)
+ {
+ SecureVector<byte> bin(input_length / 2);
+
+ u32bit written = hex_decode(&bin[0],
+ input,
+ input_length,
+ ignore_ws);
+
+ bin.truncate(written);
+ return bin;
+ }
+
+SecureVector<byte> hex_decode(const std::string& input,
+ bool ignore_ws)
+ {
+ return hex_decode(&input[0], input.size(), ignore_ws);
+ }
+
+}
diff --git a/src/codec/hex/hex.h b/src/codec/hex/hex.h
new file mode 100644
index 000000000..91a743b45
--- /dev/null
+++ b/src/codec/hex/hex.h
@@ -0,0 +1,108 @@
+/*
+* Hex Encoding and Decoding
+* (C) 2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_HEX_CODEC_H__
+#define BOTAN_HEX_CODEC_H__
+
+#include <botan/secmem.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* Perform hex encoding
+* @param output an array of at least input_length*2 bytes
+* @param input is some binary data
+* @param input_length length of input in bytes
+* @param uppercase should output be upper or lower case?
+*/
+void BOTAN_DLL hex_encode(char output[],
+ const byte input[],
+ u32bit input_length,
+ bool uppercase = true);
+
+/**
+* Perform hex encoding
+* @param input some input
+* @param input_length length of input in bytes
+* @param uppercase should output be upper or lower case?
+* @return hexadecimal representation of input
+*/
+std::string BOTAN_DLL hex_encode(const byte input[],
+ u32bit input_length,
+ bool uppercase = true);
+
+/**
+* Perform hex decoding
+* @param output an array of at least input_length/2 bytes
+* @param input some hex input
+* @param input_length length of input in bytes
+* @param input_consumed is an output parameter which says how many
+* bytes of input were actually consumed. If less than
+* input_length, then the range input[consumed:length]
+* should be passed in later along with more input.
+* @param ignore_ws ignore whitespace on input; if false, throw an
+ exception if whitespace is encountered
+* @return number of bytes written to output
+*/
+u32bit BOTAN_DLL hex_decode(byte output[],
+ const char input[],
+ u32bit input_length,
+ u32bit& input_consumed,
+ bool ignore_ws = true);
+
+/**
+* Perform hex decoding
+* @param output an array of at least input_length/2 bytes
+* @param input some hex input
+* @param input_length length of input in bytes
+* @param ignore_ws ignore whitespace on input; if false, throw an
+ exception if whitespace is encountered
+* @return number of bytes written to output
+*/
+u32bit BOTAN_DLL hex_decode(byte output[],
+ const char input[],
+ u32bit input_length,
+ bool ignore_ws = true);
+
+/**
+* Perform hex decoding
+* @param output an array of at least input_length/2 bytes
+* @param input some hex input
+* @param ignore_ws ignore whitespace on input; if false, throw an
+ exception if whitespace is encountered
+* @return number of bytes written to output
+*/
+u32bit BOTAN_DLL hex_decode(byte output[],
+ const std::string& input,
+ bool ignore_ws = true);
+
+/**
+* Perform hex decoding
+* @param input some hex input
+* @param input_length the length of input in bytes
+* @param ignore_ws ignore whitespace on input; if false, throw an
+ exception if whitespace is encountered
+* @return decoded hex output
+*/
+SecureVector<byte> BOTAN_DLL hex_decode(const char input[],
+ u32bit input_length,
+ bool ignore_ws = true);
+
+/**
+* Perform hex decoding
+* @param input some hex input
+* @param ignore_ws ignore whitespace on input; if false, throw an
+ exception if whitespace is encountered
+* @return decoded hex output
+*/
+SecureVector<byte> BOTAN_DLL hex_decode(const std::string& input,
+ bool ignore_ws = true);
+
+}
+
+#endif
diff --git a/src/codec/hex/info.txt b/src/codec/hex/info.txt
new file mode 100644
index 000000000..c9eb8fb73
--- /dev/null
+++ b/src/codec/hex/info.txt
@@ -0,0 +1 @@
+define HEX_CODEC
diff --git a/src/filters/filters.h b/src/filters/filters.h
index e2c7cb5ec..51b4f00fe 100644
--- a/src/filters/filters.h
+++ b/src/filters/filters.h
@@ -24,8 +24,8 @@
#include <botan/base64.h>
#endif
-#if defined(BOTAN_HAS_HEX_CODEC)
- #include <botan/hex.h>
+#if defined(BOTAN_HAS_HEX_FILTER)
+ #include <botan/hex_filt.h>
#endif
namespace Botan {
diff --git a/src/filters/hex/hex_char.cpp b/src/filters/hex/hex_char.cpp
deleted file mode 100644
index c28efc5f7..000000000
--- a/src/filters/hex/hex_char.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-* Hex Character Table
-* (C) 1999-2008 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/hex.h>
-
-namespace Botan {
-
-/*
-* Hex Encoder Lookup Tables
-*/
-const byte Hex_Encoder::BIN_TO_HEX_UPPER[16] = {
-0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43,
-0x44, 0x45, 0x46 };
-
-const byte Hex_Encoder::BIN_TO_HEX_LOWER[16] = {
-0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63,
-0x64, 0x65, 0x66 };
-
-/*
-* Hex Decoder Lookup Table
-*/
-const byte Hex_Decoder::HEX_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, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x01, 0x02, 0x03,
-0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
-0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 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, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 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, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
-0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
-
-}
diff --git a/src/filters/hex/hex.cpp b/src/filters/hex_filt/hex_filt.cpp
index 7191e1554..0f3daa464 100644
--- a/src/filters/hex/hex.cpp
+++ b/src/filters/hex_filt/hex_filt.cpp
@@ -5,6 +5,7 @@
* Distributed under the terms of the Botan license
*/
+#include <botan/hex_filt.h>
#include <botan/hex.h>
#include <botan/parsing.h>
#include <botan/charset.h>
@@ -40,24 +41,13 @@ Hex_Encoder::Hex_Encoder(Case c) : casing(c), line_length(0)
}
/*
-* Hex Encoding Operation
-*/
-void Hex_Encoder::encode(byte in, byte out[2], Hex_Encoder::Case casing)
- {
- const byte* BIN_TO_HEX = ((casing == Uppercase) ? BIN_TO_HEX_UPPER :
- BIN_TO_HEX_LOWER);
-
- out[0] = BIN_TO_HEX[((in >> 4) & 0x0F)];
- out[1] = BIN_TO_HEX[((in ) & 0x0F)];
- }
-
-/*
* Encode and send a block
*/
void Hex_Encoder::encode_and_send(const byte block[], u32bit length)
{
- for(u32bit j = 0; j != length; ++j)
- encode(block[j], out + 2*j, casing);
+ hex_encode(reinterpret_cast<char*>(&out[0]),
+ block, length,
+ casing == Uppercase);
if(line_length == 0)
send(out, 2*length);
@@ -125,62 +115,35 @@ Hex_Decoder::Hex_Decoder(Decoder_Checking c) : checking(c)
}
/*
-* Check if a character is a valid hex char
-*/
-bool Hex_Decoder::is_valid(byte in)
- {
- return (HEX_TO_BIN[in] != 0x80);
- }
-
-/*
-* Handle processing an invalid character
-*/
-void Hex_Decoder::handle_bad_char(byte c)
- {
- if(checking == NONE)
- return;
-
- if((checking == IGNORE_WS) && Charset::is_space(c))
- return;
-
- throw Decoding_Error("Hex_Decoder: Invalid hex character: " +
- to_string(c));
- }
-
-/*
-* Hex Decoding Operation
-*/
-byte Hex_Decoder::decode(const byte hex[2])
- {
- return ((HEX_TO_BIN[hex[0]] << 4) | HEX_TO_BIN[hex[1]]);
- }
-
-/*
-* Decode and send a block
-*/
-void Hex_Decoder::decode_and_send(const byte block[], u32bit length)
- {
- for(u32bit j = 0; j != length / 2; ++j)
- out[j] = decode(block + 2*j);
- send(out, length / 2);
- }
-
-/*
* Convert some data from hex format
*/
void Hex_Decoder::write(const byte input[], u32bit length)
{
- for(u32bit j = 0; j != length; ++j)
+ while(length)
{
- if(is_valid(input[j]))
- in[position++] = input[j];
- else
- handle_bad_char(input[j]);
- if(position == in.size())
+ u32bit to_copy = std::min(length, in.size() - position);
+ copy_mem(&in[position], input, to_copy);
+ position += to_copy;
+
+ u32bit consumed = 0;
+ u32bit written = hex_decode(&out[0],
+ reinterpret_cast<const char*>(&in[0]),
+ position,
+ consumed,
+ checking != FULL_CHECK);
+
+ send(out, written);
+
+ if(consumed != position)
{
- decode_and_send(in, in.size());
- position = 0;
+ copy_mem(&in[0], &in[consumed], position - consumed);
+ position = position - consumed;
}
+ else
+ position = 0;
+
+ length -= to_copy;
+ input += to_copy;
}
}
@@ -189,8 +152,21 @@ void Hex_Decoder::write(const byte input[], u32bit length)
*/
void Hex_Decoder::end_msg()
{
- decode_and_send(in, position);
+ u32bit consumed = 0;
+ u32bit written = hex_decode(&out[0],
+ reinterpret_cast<const char*>(&in[0]),
+ position,
+ consumed,
+ checking != FULL_CHECK);
+
+ send(out, written);
+
+ const bool not_full_bytes = consumed != position;
+
position = 0;
+
+ if(not_full_bytes)
+ throw std::invalid_argument("Hex_Decoder: Input not full bytes");
}
}
diff --git a/src/filters/hex/hex.h b/src/filters/hex_filt/hex_filt.h
index 6698a61be..2a7300ddb 100644
--- a/src/filters/hex/hex.h
+++ b/src/filters/hex_filt/hex_filt.h
@@ -5,8 +5,8 @@
* Distributed under the terms of the Botan license
*/
-#ifndef BOTAN_HEX_H__
-#define BOTAN_HEX_H__
+#ifndef BOTAN_HEX_FILTER_H__
+#define BOTAN_HEX_FILTER_H__
#include <botan/filter.h>
@@ -50,8 +50,6 @@ class BOTAN_DLL Hex_Encoder : public Filter
Case the_case = Uppercase);
private:
void encode_and_send(const byte[], u32bit);
- static const byte BIN_TO_HEX_UPPER[16];
- static const byte BIN_TO_HEX_LOWER[16];
const Case casing;
const u32bit line_length;
@@ -65,20 +63,6 @@ class BOTAN_DLL Hex_Encoder : public Filter
class BOTAN_DLL Hex_Decoder : public Filter
{
public:
- /**
- * Decode a pair of hex chars to a byte
- * @param in an array of two hex chars
- * @return byte formed by decoding in
- */
- static byte decode(const byte in[2]);
-
- /**
- * Check if this character is a valid hex input
- * @param c a single character
- * @return true iff c is a valid hex char
- */
- static bool is_valid(byte c);
-
std::string name() const { return "Hex_Decoder"; }
void write(const byte[], u32bit);
@@ -91,10 +75,6 @@ class BOTAN_DLL Hex_Decoder : public Filter
*/
Hex_Decoder(Decoder_Checking checking = NONE);
private:
- void decode_and_send(const byte[], u32bit);
- void handle_bad_char(byte);
- static const byte HEX_TO_BIN[256];
-
const Decoder_Checking checking;
SecureVector<byte> in, out;
u32bit position;
diff --git a/src/filters/hex/info.txt b/src/filters/hex_filt/info.txt
index 0a4205669..7f5f47fa1 100644
--- a/src/filters/hex/info.txt
+++ b/src/filters/hex_filt/info.txt
@@ -1,4 +1,4 @@
-define HEX_CODEC
+define HEX_FILTER
<requires>
filters