diff options
author | AnotherTest <ali.mpfard@gmail.com> | 2021-04-18 13:40:40 +0430 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-04-18 14:18:16 +0200 |
commit | ed28008d78e5d5f315d08058679dfc10e607fd9d (patch) | |
tree | 9ace2ca679c97f1b683ab69037a3cf03f7d4f599 /Userland/Libraries/LibCrypto | |
parent | 65de2d236df19be626ad6ba3b4474fee65643088 (diff) | |
download | serenity-ed28008d78e5d5f315d08058679dfc10e607fd9d.zip |
LibCrypo: Add an ASN.1/DER pretty-printer
It's much easier to debug things when we can actually *see* them :P
Diffstat (limited to 'Userland/Libraries/LibCrypto')
-rw-r--r-- | Userland/Libraries/LibCrypto/ASN1/DER.cpp | 141 | ||||
-rw-r--r-- | Userland/Libraries/LibCrypto/ASN1/DER.h | 2 |
2 files changed, 143 insertions, 0 deletions
diff --git a/Userland/Libraries/LibCrypto/ASN1/DER.cpp b/Userland/Libraries/LibCrypto/ASN1/DER.cpp index d09c7ee87e..50b7149a8b 100644 --- a/Userland/Libraries/LibCrypto/ASN1/DER.cpp +++ b/Userland/Libraries/LibCrypto/ASN1/DER.cpp @@ -273,6 +273,147 @@ Optional<DecodeError> Decoder::leave() return {}; } +void pretty_print(Decoder& decoder, OutputStream& stream, int indent) +{ + while (!decoder.eof()) { + auto tag = decoder.peek(); + if (tag.is_error()) { + dbgln("PrettyPrint error: {}", tag.error()); + return; + } + + StringBuilder builder; + for (int i = 0; i < indent; ++i) + builder.append(' '); + builder.appendff("<{}> ", class_name(tag.value().class_)); + if (tag.value().type == Type::Constructed) { + builder.appendff("[{}] {} ({})", type_name(tag.value().type), static_cast<u8>(tag.value().kind), kind_name(tag.value().kind)); + if (auto error = decoder.enter(); error.has_value()) { + dbgln("Constructed PrettyPrint error: {}", error.value()); + return; + } + + builder.append('\n'); + stream.write(builder.string_view().bytes()); + + pretty_print(decoder, stream, indent + 2); + + if (auto error = decoder.leave(); error.has_value()) { + dbgln("Constructed PrettyPrint error: {}", error.value()); + return; + } + + continue; + } else { + if (tag.value().class_ != Class::Universal) + builder.appendff("[{}] {} {}", type_name(tag.value().type), static_cast<u8>(tag.value().kind), kind_name(tag.value().kind)); + else + builder.appendff("[{}] {}", type_name(tag.value().type), kind_name(tag.value().kind)); + switch (tag.value().kind) { + case Kind::Eol: { + auto value = decoder.read<ReadonlyBytes>(); + if (value.is_error()) { + dbgln("EOL PrettyPrint error: {}", value.error()); + return; + } + break; + } + case Kind::Boolean: { + auto value = decoder.read<bool>(); + if (value.is_error()) { + dbgln("Bool PrettyPrint error: {}", value.error()); + return; + } + builder.appendff(" {}", value.value()); + break; + } + case Kind::Integer: { + auto value = decoder.read<ReadonlyBytes>(); + if (value.is_error()) { + dbgln("Integer PrettyPrint error: {}", value.error()); + return; + } + builder.append(" 0x"); + for (auto ch : value.value()) + builder.appendff("{:0>2x}", ch); + break; + } + case Kind::BitString: { + auto value = decoder.read<const BitmapView>(); + if (value.is_error()) { + dbgln("BitString PrettyPrint error: {}", value.error()); + return; + } + builder.append(" 0b"); + for (size_t i = 0; i < value.value().size(); ++i) + builder.append(value.value().get(i) ? '1' : '0'); + break; + } + case Kind::OctetString: { + auto value = decoder.read<StringView>(); + if (value.is_error()) { + dbgln("OctetString PrettyPrint error: {}", value.error()); + return; + } + builder.append(" 0x"); + for (auto ch : value.value()) + builder.appendff("{:0>2x}", ch); + break; + } + case Kind::Null: { + auto value = decoder.read<decltype(nullptr)>(); + if (value.is_error()) { + dbgln("Bool PrettyPrint error: {}", value.error()); + return; + } + break; + } + case Kind::ObjectIdentifier: { + auto value = decoder.read<Vector<int>>(); + if (value.is_error()) { + dbgln("Identifier PrettyPrint error: {}", value.error()); + return; + } + for (auto& id : value.value()) + builder.appendff(" {}", id); + break; + } + case Kind::UTCTime: + case Kind::GeneralizedTime: + case Kind::IA5String: + case Kind::PrintableString: { + auto value = decoder.read<StringView>(); + if (value.is_error()) { + dbgln("String PrettyPrint error: {}", value.error()); + return; + } + builder.append(' '); + builder.append(value.value()); + break; + } + case Kind::Utf8String: { + auto value = decoder.read<Utf8View>(); + if (value.is_error()) { + dbgln("UTF8 PrettyPrint error: {}", value.error()); + return; + } + builder.append(' '); + for (auto cp : value.value()) + builder.append_code_point(cp); + break; + } + case Kind::Sequence: + case Kind::Set: + dbgln("Seq/Sequence PrettyPrint error: Unexpected Primtive"); + return; + } + } + + builder.append('\n'); + stream.write(builder.string_view().bytes()); + } +} + } void AK::Formatter<Crypto::ASN1::DecodeError>::format(FormatBuilder& fmtbuilder, Crypto::ASN1::DecodeError error) diff --git a/Userland/Libraries/LibCrypto/ASN1/DER.h b/Userland/Libraries/LibCrypto/ASN1/DER.h index 3e092353ff..1fbc960788 100644 --- a/Userland/Libraries/LibCrypto/ASN1/DER.h +++ b/Userland/Libraries/LibCrypto/ASN1/DER.h @@ -216,6 +216,8 @@ private: Optional<Tag> m_current_tag; }; +void pretty_print(Decoder&, OutputStream&, int indent = 0); + } template<> |