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/internal/fmt.h>
21bool all_printable_chars(
const uint8_t bits[],
size_t bits_len)
23 for(
size_t i = 0; i != bits_len; ++i)
29 if((std::isalnum(c) || c ==
'.' || c ==
':' || c ==
'/' || c ==
'-') ==
false)
38bool possibly_a_general_name(
const uint8_t bits[],
size_t bits_len)
43 if(bits[0] != 0x82 && bits[0] != 0x86)
46 if(bits[1] != bits_len - 2)
49 if(all_printable_chars(bits + 2, bits_len - 2) ==
false)
59 std::ostringstream output;
69 decode(output, dec, 0);
72void ASN1_Formatter::decode(std::ostream& output,
78 const bool recurse_deeper = (m_max_depth == 0 || level < m_max_depth);
84 const size_t length = obj.
length();
88 std::vector<uint8_t> bits;
99 output <<
format(type_tag, class_tag, level, length,
"");
100 decode(output, cons_info, level + 1);
104 output <<
format(type_tag, class_tag, level, length,
110 bool success_parsing_cs =
false;
112 if(m_print_context_specific)
116 if(possibly_a_general_name(bits.data(), bits.size()))
118 output <<
format(type_tag, class_tag, level, level,
120 success_parsing_cs =
true;
122 else if(recurse_deeper)
124 std::vector<uint8_t> inner_bits;
125 data.decode(inner_bits, type_tag);
127 BER_Decoder inner(inner_bits);
128 std::ostringstream inner_data;
129 decode(inner_data, inner, level + 1);
130 output << inner_data.str();
131 success_parsing_cs =
true;
139 if(success_parsing_cs ==
false)
141 output <<
format(type_tag, class_tag, level, length,
150 const std::string
name = oid.human_name_or_empty();
151 const std::string oid_str = oid.to_string();
155 output <<
format(type_tag, class_tag, level, length, oid_str);
159 output <<
format(type_tag, class_tag, level, length,
160 fmt(
"{} [{}]",
name, oid_str));
176 output <<
format(type_tag, class_tag, level, length,
format_bn(number));
181 data.decode(
boolean);
182 output <<
format(type_tag, class_tag, level, length, (
boolean ?
"true" :
"false"));
186 output <<
format(type_tag, class_tag, level, length,
"");
190 std::vector<uint8_t> decoded_bits;
191 data.decode(decoded_bits, type_tag);
192 bool printing_octet_string_worked =
false;
198 BER_Decoder inner(decoded_bits);
200 std::ostringstream inner_data;
201 decode(inner_data, inner, level + 1);
203 output <<
format(type_tag, class_tag, level, length,
"");
204 output << inner_data.str();
205 printing_octet_string_worked =
true;
212 if(!printing_octet_string_worked)
214 output <<
format(type_tag, class_tag, level, length,
215 format_bin(type_tag, class_tag, decoded_bits));
222 output <<
format(type_tag, class_tag, level, length, str.value());
228 output <<
format(type_tag, class_tag, level, length, time.readable_string());
232 output <<
"Unknown ASN.1 tag class=" <<
static_cast<int>(class_tag)
233 <<
" type=" <<
static_cast<int>(type_tag) <<
"\n";
250 std::ostringstream oss;
255 oss <<
"[" << std::to_string(
static_cast<uint32_t
>(type_tag)) <<
"]";
271std::string ASN1_Pretty_Printer::format(
ASN1_Type type_tag,
275 std::string_view value)
const
277 bool should_skip =
false;
279 if(value.length() > m_print_limit)
285 value.length() > m_print_binary_limit)
290 level += m_initial_level;
292 std::ostringstream oss;
294 oss <<
" d=" << std::setw(2) << level
295 <<
", l=" << std::setw(4) << length <<
":"
296 << std::string(level + 1,
' ') << format_type(type_tag, class_tag);
298 if(!value.empty() && !should_skip)
300 const size_t current_pos =
static_cast<size_t>(oss.tellp());
301 const size_t spaces_to_align =
302 (current_pos >= m_value_column) ? 1 : (m_value_column - current_pos);
304 oss << std::string(spaces_to_align,
' ') << value;
312std::string ASN1_Pretty_Printer::format_bin(
ASN1_Type ,
314 const std::vector<uint8_t>& vec)
const
316 if(all_printable_chars(vec.data(), vec.size()))
324std::string ASN1_Pretty_Printer::format_bn(
const BigInt& bn)
const
327 return bn.to_dec_string();
329 return bn.to_hex_string();
static bool is_string_type(ASN1_Type tag)
BER_Object get_next_object()
const uint8_t * bits() const
ASN1_Class get_class() const
DER_Encoder & add_object(ASN1_Type type_tag, ASN1_Class class_tag, const uint8_t rep[], size_t length)
std::string asn1_tag_to_string(ASN1_Type type)
std::string fmt(std::string_view format, const T &... args)
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
const char * cast_uint8_ptr_to_char(const uint8_t *b)
bool intersects(ASN1_Class x, ASN1_Class y)