Botan
1.11.15
|
00001 /* 00002 * Hex Encoder/Decoder 00003 * (C) 1999-2007 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/hex_filt.h> 00009 #include <botan/hex.h> 00010 #include <botan/parsing.h> 00011 #include <botan/charset.h> 00012 #include <botan/exceptn.h> 00013 #include <algorithm> 00014 00015 namespace Botan { 00016 00017 /** 00018 * Size used for internal buffer in hex encoder/decoder 00019 */ 00020 const size_t HEX_CODEC_BUFFER_SIZE = 256; 00021 00022 /* 00023 * Hex_Encoder Constructor 00024 */ 00025 Hex_Encoder::Hex_Encoder(bool breaks, size_t length, Case c) : 00026 casing(c), line_length(breaks ? length : 0) 00027 { 00028 in.resize(HEX_CODEC_BUFFER_SIZE); 00029 out.resize(2*in.size()); 00030 counter = position = 0; 00031 } 00032 00033 /* 00034 * Hex_Encoder Constructor 00035 */ 00036 Hex_Encoder::Hex_Encoder(Case c) : casing(c), line_length(0) 00037 { 00038 in.resize(HEX_CODEC_BUFFER_SIZE); 00039 out.resize(2*in.size()); 00040 counter = position = 0; 00041 } 00042 00043 /* 00044 * Encode and send a block 00045 */ 00046 void Hex_Encoder::encode_and_send(const byte block[], size_t length) 00047 { 00048 hex_encode(reinterpret_cast<char*>(&out[0]), 00049 block, length, 00050 casing == Uppercase); 00051 00052 if(line_length == 0) 00053 send(out, 2*length); 00054 else 00055 { 00056 size_t remaining = 2*length, offset = 0; 00057 while(remaining) 00058 { 00059 size_t sent = std::min(line_length - counter, remaining); 00060 send(&out[offset], sent); 00061 counter += sent; 00062 remaining -= sent; 00063 offset += sent; 00064 if(counter == line_length) 00065 { 00066 send('\n'); 00067 counter = 0; 00068 } 00069 } 00070 } 00071 } 00072 00073 /* 00074 * Convert some data into hex format 00075 */ 00076 void Hex_Encoder::write(const byte input[], size_t length) 00077 { 00078 buffer_insert(in, position, input, length); 00079 if(position + length >= in.size()) 00080 { 00081 encode_and_send(&in[0], in.size()); 00082 input += (in.size() - position); 00083 length -= (in.size() - position); 00084 while(length >= in.size()) 00085 { 00086 encode_and_send(input, in.size()); 00087 input += in.size(); 00088 length -= in.size(); 00089 } 00090 copy_mem(&in[0], input, length); 00091 position = 0; 00092 } 00093 position += length; 00094 } 00095 00096 /* 00097 * Flush buffers 00098 */ 00099 void Hex_Encoder::end_msg() 00100 { 00101 encode_and_send(&in[0], position); 00102 if(counter && line_length) 00103 send('\n'); 00104 counter = position = 0; 00105 } 00106 00107 /* 00108 * Hex_Decoder Constructor 00109 */ 00110 Hex_Decoder::Hex_Decoder(Decoder_Checking c) : checking(c) 00111 { 00112 in.resize(HEX_CODEC_BUFFER_SIZE); 00113 out.resize(in.size() / 2); 00114 position = 0; 00115 } 00116 00117 /* 00118 * Convert some data from hex format 00119 */ 00120 void Hex_Decoder::write(const byte input[], size_t length) 00121 { 00122 while(length) 00123 { 00124 size_t to_copy = std::min<size_t>(length, in.size() - position); 00125 copy_mem(&in[position], input, to_copy); 00126 position += to_copy; 00127 00128 size_t consumed = 0; 00129 size_t written = hex_decode(&out[0], 00130 reinterpret_cast<const char*>(&in[0]), 00131 position, 00132 consumed, 00133 checking != FULL_CHECK); 00134 00135 send(out, written); 00136 00137 if(consumed != position) 00138 { 00139 copy_mem(&in[0], &in[consumed], position - consumed); 00140 position = position - consumed; 00141 } 00142 else 00143 position = 0; 00144 00145 length -= to_copy; 00146 input += to_copy; 00147 } 00148 } 00149 00150 /* 00151 * Flush buffers 00152 */ 00153 void Hex_Decoder::end_msg() 00154 { 00155 size_t consumed = 0; 00156 size_t written = hex_decode(&out[0], 00157 reinterpret_cast<const char*>(&in[0]), 00158 position, 00159 consumed, 00160 checking != FULL_CHECK); 00161 00162 send(out, written); 00163 00164 const bool not_full_bytes = consumed != position; 00165 00166 position = 0; 00167 00168 if(not_full_bytes) 00169 throw std::invalid_argument("Hex_Decoder: Input not full bytes"); 00170 } 00171 00172 }