7 #include <botan/asn1_print.h>
8 #include <botan/bigint.h>
10 #include <botan/der_enc.h>
11 #include <botan/ber_dec.h>
12 #include <botan/asn1_time.h>
13 #include <botan/asn1_str.h>
14 #include <botan/oids.h>
23 bool all_printable_chars(
const uint8_t bits[],
size_t bits_len)
25 for(
size_t i = 0; i != bits_len; ++i)
31 if((std::isalnum(c) || c ==
'.' || c ==
':' || c ==
'/' || c ==
'-') ==
false)
40 bool possibly_a_general_name(
const uint8_t bits[],
size_t bits_len)
45 if(bits[0] != 0x82 && bits[0] != 0x86)
48 if(bits[1] != bits_len - 2)
51 if(all_printable_chars(bits + 2, bits_len - 2) ==
false)
61 std::ostringstream output;
71 decode(output, dec, 0);
74 void ASN1_Formatter::decode(std::ostream& output,
80 const bool recurse_deeper = (m_max_depth == 0 || level < m_max_depth);
86 const size_t length = obj.
length();
90 std::vector<uint8_t> bits;
101 output <<
format(type_tag, class_tag, level, length,
"");
102 decode(output, cons_info, level + 1);
106 output <<
format(type_tag, class_tag, level, length,
112 bool success_parsing_cs =
false;
114 if(m_print_context_specific)
118 if(possibly_a_general_name(bits.data(), bits.size()))
120 output <<
format(type_tag, class_tag, level, level,
122 success_parsing_cs =
true;
124 else if(recurse_deeper)
126 std::vector<uint8_t> inner_bits;
127 data.decode(inner_bits, type_tag);
129 BER_Decoder inner(inner_bits);
130 std::ostringstream inner_data;
131 decode(inner_data, inner, level + 1);
132 output << inner_data.str();
133 success_parsing_cs =
true;
141 if(success_parsing_cs ==
false)
143 output <<
format(type_tag, class_tag, level, length,
155 out = oid.to_string();
159 out +=
" [" + oid.to_string() +
"]";
162 output <<
format(type_tag, class_tag, level, length, out);
186 data.decode(
boolean);
187 output <<
format(type_tag, class_tag, level, length, (
boolean ?
"true" :
"false"));
191 output <<
format(type_tag, class_tag, level, length,
"");
195 std::vector<uint8_t> decoded_bits;
196 data.decode(decoded_bits, type_tag);
197 bool printing_octet_string_worked =
false;
203 BER_Decoder inner(decoded_bits);
205 std::ostringstream inner_data;
206 decode(inner_data, inner, level + 1);
208 output <<
format(type_tag, class_tag, level, length,
"");
209 output << inner_data.str();
210 printing_octet_string_worked =
true;
217 if(!printing_octet_string_worked)
219 output <<
format(type_tag, class_tag, level, length,
220 format_bin(type_tag, class_tag, decoded_bits));
227 output <<
format(type_tag, class_tag, level, length, str.value());
233 output <<
format(type_tag, class_tag, level, length, time.readable_string());
237 output <<
"Unknown ASN.1 tag class=" <<
static_cast<int>(class_tag)
238 <<
" type=" << static_cast<int>(type_tag) <<
"\n";
252 if(class_tag == CONSTRUCTED && (type_tag ==
SEQUENCE || type_tag ==
SET))
257 if(class_tag & CONSTRUCTED)
262 if(class_tag & APPLICATION)
266 if(class_tag & CONTEXT_SPECIFIC)
276 std::string ASN1_Pretty_Printer::format(
ASN1_Tag type_tag,
280 const std::string& value)
const
282 bool should_skip =
false;
284 if(value.length() > m_print_limit)
290 value.length() > m_print_binary_limit)
295 level += m_initial_level;
297 std::ostringstream oss;
299 oss <<
" d=" << std::setw(2) << level
300 <<
", l=" << std::setw(4) << length <<
":"
301 << std::string(level + 1,
' ') << format_type(type_tag, class_tag);
303 if(value !=
"" && !should_skip)
305 const size_t current_pos =
static_cast<size_t>(oss.tellp());
306 const size_t spaces_to_align =
307 (current_pos >= m_value_column) ? 1 : (m_value_column - current_pos);
309 oss << std::string(spaces_to_align,
' ') << value;
317 std::string ASN1_Pretty_Printer::format_bin(
ASN1_Tag ,
319 const std::vector<uint8_t>& vec)
const
321 if(all_printable_chars(vec.data(), vec.size()))
std::string asn1_tag_to_string(ASN1_Tag type)
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
DER_Encoder & add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, const uint8_t rep[], size_t length)
static bool is_string_type(ASN1_Tag tag)
static std::vector< uint8_t > encode(const BigInt &n)
BOTAN_UNSTABLE_API std::string oid2str_or_empty(const OID &oid)
std::string to_string(const BER_Object &obj)
const uint8_t * bits() const
ASN1_Tag get_class() const
BER_Object get_next_object()
const char * cast_uint8_ptr_to_char(const uint8_t *b)