Selaa lähdekoodia

LibCrypto: Use `ErrorOr` error handling for parsing DER

This replaces a mixture of `Result`, `Optional`, and a custom error enum
with our usual `ErrorOr`-based error handling.
Tim Schumacher 2 vuotta sitten
vanhempi
commit
f5fb1396e8

+ 67 - 140
Userland/Libraries/LibCrypto/ASN1/DER.cpp

@@ -11,7 +11,7 @@
 
 namespace Crypto::ASN1 {
 
-Result<Tag, DecodeError> Decoder::read_tag()
+ErrorOr<Tag> Decoder::read_tag()
 {
     auto byte = TRY(read_byte());
     u8 class_ = byte & 0xc0;
@@ -29,7 +29,7 @@ Result<Tag, DecodeError> Decoder::read_tag()
     return Tag { (Kind)kind, (Class)class_, (Type)type };
 }
 
-Result<size_t, DecodeError> Decoder::read_length()
+ErrorOr<size_t> Decoder::read_length()
 {
     auto byte = TRY(read_byte());
     size_t length = byte;
@@ -37,13 +37,13 @@ Result<size_t, DecodeError> Decoder::read_length()
     if (byte & 0x80) {
         auto count = byte & 0x7f;
         if (count == 0x7f)
-            return DecodeError::InvalidInputFormat;
+            return Error::from_string_literal("ASN1::Decoder: Length has an invalid count value");
 
         auto data = TRY(read_bytes(count));
         length = 0;
 
         if (data.size() > sizeof(size_t))
-            return DecodeError::Overflow;
+            return Error::from_string_literal("ASN1::Decoder: Length is larger than the target type");
 
         for (auto&& byte : data)
             length = (length << 8) | (size_t)byte;
@@ -52,14 +52,14 @@ Result<size_t, DecodeError> Decoder::read_length()
     return length;
 }
 
-Result<u8, DecodeError> Decoder::read_byte()
+ErrorOr<u8> Decoder::read_byte()
 {
     if (m_stack.is_empty())
-        return DecodeError::NoInput;
+        return Error::from_string_literal("ASN1::Decoder: Reading byte from an empty stack");
 
     auto& entry = m_stack.last();
     if (entry.is_empty())
-        return DecodeError::NotEnoughData;
+        return Error::from_string_literal("ASN1::Decoder: Reading byte from an empty entry");
 
     auto byte = entry[0];
     entry = entry.slice(1);
@@ -67,14 +67,14 @@ Result<u8, DecodeError> Decoder::read_byte()
     return byte;
 }
 
-Result<ReadonlyBytes, DecodeError> Decoder::read_bytes(size_t length)
+ErrorOr<ReadonlyBytes> Decoder::read_bytes(size_t length)
 {
     if (m_stack.is_empty())
-        return DecodeError::NoInput;
+        return Error::from_string_literal("ASN1::Decoder: Reading bytes from an empty stack");
 
     auto& entry = m_stack.last();
     if (entry.size() < length)
-        return DecodeError::NotEnoughData;
+        return Error::from_string_literal("ASN1::Decoder: Reading bytes from an empty entry");
 
     auto bytes = entry.slice(0, length);
     entry = entry.slice(length);
@@ -82,46 +82,46 @@ Result<ReadonlyBytes, DecodeError> Decoder::read_bytes(size_t length)
     return bytes;
 }
 
-Result<bool, DecodeError> Decoder::decode_boolean(ReadonlyBytes data)
+ErrorOr<bool> Decoder::decode_boolean(ReadonlyBytes data)
 {
     if (data.size() != 1)
-        return DecodeError::InvalidInputFormat;
+        return Error::from_string_literal("ASN1::Decoder: Decoding boolean from a non boolean-sized span");
 
     return data[0] != 0;
 }
 
-Result<UnsignedBigInteger, DecodeError> Decoder::decode_arbitrary_sized_integer(ReadonlyBytes data)
+ErrorOr<UnsignedBigInteger> Decoder::decode_arbitrary_sized_integer(ReadonlyBytes data)
 {
     if (data.size() < 1)
-        return DecodeError::NotEnoughData;
+        return Error::from_string_literal("ASN1::Decoder: Decoding arbitrary sized integer from an empty span");
 
     if (data.size() > 1
         && ((data[0] == 0xff && data[1] & 0x80)
             || (data[0] == 0x00 && !(data[1] & 0x80)))) {
-        return DecodeError::InvalidInputFormat;
+        return Error::from_string_literal("ASN1::Decoder: Arbitrary sized integer has an invalid format");
     }
 
     bool is_negative = data[0] & 0x80;
     if (is_negative)
-        return DecodeError::UnsupportedFormat;
+        return Error::from_string_literal("ASN1::Decoder: Decoding a negative unsigned arbitrary sized integer");
 
     return UnsignedBigInteger::import_data(data.data(), data.size());
 }
 
-Result<StringView, DecodeError> Decoder::decode_octet_string(ReadonlyBytes bytes)
+ErrorOr<StringView> Decoder::decode_octet_string(ReadonlyBytes bytes)
 {
     return StringView { bytes.data(), bytes.size() };
 }
 
-Result<nullptr_t, DecodeError> Decoder::decode_null(ReadonlyBytes data)
+ErrorOr<nullptr_t> Decoder::decode_null(ReadonlyBytes data)
 {
     if (data.size() != 0)
-        return DecodeError::InvalidInputFormat;
+        return Error::from_string_literal("ASN1::Decoder: Decoding null from a non-empty span");
 
     return nullptr;
 }
 
-Result<Vector<int>, DecodeError> Decoder::decode_object_identifier(ReadonlyBytes data)
+ErrorOr<Vector<int>> Decoder::decode_object_identifier(ReadonlyBytes data)
 {
     Vector<int> result;
     result.append(0); // Reserved space.
@@ -129,7 +129,7 @@ Result<Vector<int>, DecodeError> Decoder::decode_object_identifier(ReadonlyBytes
     u32 value = 0;
     for (auto&& byte : data) {
         if (value == 0 && byte == 0x80)
-            return DecodeError::InvalidInputFormat;
+            return Error::from_string_literal("ASN1::Decoder: Invalid first byte in object identifier");
 
         value = (value << 7) | (byte & 0x7f);
         if (!(byte & 0x80)) {
@@ -139,7 +139,7 @@ Result<Vector<int>, DecodeError> Decoder::decode_object_identifier(ReadonlyBytes
     }
 
     if (result.size() == 1 || result[1] >= 1600)
-        return DecodeError::InvalidInputFormat;
+        return Error::from_string_literal("ASN1::Decoder: Invalid encoding in object identifier");
 
     result[0] = result[1] / 40;
     result[1] = result[1] % 40;
@@ -147,36 +147,36 @@ Result<Vector<int>, DecodeError> Decoder::decode_object_identifier(ReadonlyBytes
     return result;
 }
 
-Result<StringView, DecodeError> Decoder::decode_printable_string(ReadonlyBytes data)
+ErrorOr<StringView> Decoder::decode_printable_string(ReadonlyBytes data)
 {
     Utf8View view { data };
     if (!view.validate())
-        return DecodeError::InvalidInputFormat;
+        return Error::from_string_literal("ASN1::Decoder: Invalid UTF-8 in printable string");
 
     return StringView { data };
 }
 
-Result<BitStringView, DecodeError> Decoder::decode_bit_string(ReadonlyBytes data)
+ErrorOr<BitStringView> Decoder::decode_bit_string(ReadonlyBytes data)
 {
     if (data.size() < 1)
-        return DecodeError::InvalidInputFormat;
+        return Error::from_string_literal("ASN1::Decoder: Decoding bit string from empty span");
 
     auto unused_bits = data[0];
     auto total_size_in_bits = (data.size() - 1) * 8;
 
     if (unused_bits > total_size_in_bits)
-        return DecodeError::Overflow;
+        return Error::from_string_literal("ASN1::Decoder: Number of unused bits is larger than the total size");
 
     return BitStringView { data.slice(1), unused_bits };
 }
 
-Result<Tag, DecodeError> Decoder::peek()
+ErrorOr<Tag> Decoder::peek()
 {
     if (m_stack.is_empty())
-        return DecodeError::NoInput;
+        return Error::from_string_literal("ASN1::Decoder: Peeking using an empty stack");
 
     if (eof())
-        return DecodeError::EndOfStream;
+        return Error::from_string_literal("ASN1::Decoder: Peeking using a decoder that is at EOF");
 
     if (m_current_tag.has_value())
         return m_current_tag.value();
@@ -191,14 +191,14 @@ bool Decoder::eof() const
     return m_stack.is_empty() || m_stack.last().is_empty();
 }
 
-Optional<DecodeError> Decoder::enter()
+ErrorOr<void> Decoder::enter()
 {
     if (m_stack.is_empty())
-        return DecodeError::NoInput;
+        return Error::from_string_literal("ASN1::Decoder: Entering using an empty stack");
 
     auto tag = TRY(peek());
     if (tag.type != Type::Constructed)
-        return DecodeError::EnteringNonConstructedTag;
+        return Error::from_string_literal("ASN1::Decoder: Entering a non-constructed type");
 
     auto length = TRY(read_length());
 
@@ -210,13 +210,13 @@ Optional<DecodeError> Decoder::enter()
     return {};
 }
 
-Optional<DecodeError> Decoder::leave()
+ErrorOr<void> Decoder::leave()
 {
     if (m_stack.is_empty())
-        return DecodeError::NoInput;
+        return Error::from_string_literal("ASN1::Decoder: Leaving using an empty stack");
 
     if (m_stack.size() == 1)
-        return DecodeError::LeavingMainContext;
+        return Error::from_string_literal("ASN1::Decoder: Leaving the main context");
 
     m_stack.take_last();
     m_current_tag.clear();
@@ -224,108 +224,70 @@ Optional<DecodeError> Decoder::leave()
     return {};
 }
 
-void pretty_print(Decoder& decoder, DeprecatedOutputStream& stream, int indent)
+ErrorOr<void> pretty_print(Decoder& decoder, DeprecatedOutputStream& stream, int indent)
 {
     while (!decoder.eof()) {
-        auto tag = decoder.peek();
-        if (tag.is_error()) {
-            dbgln("PrettyPrint error: {}", tag.error());
-            return;
-        }
+        auto tag = TRY(decoder.peek());
 
         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.appendff("<{}> ", class_name(tag.class_));
+        if (tag.type == Type::Constructed) {
+            builder.appendff("[{}] {} ({})", type_name(tag.type), static_cast<u8>(tag.kind), kind_name(tag.kind));
+            TRY(decoder.enter());
 
             builder.append('\n');
             stream.write(builder.string_view().bytes());
 
-            pretty_print(decoder, stream, indent + 2);
+            TRY(pretty_print(decoder, stream, indent + 2));
 
-            if (auto error = decoder.leave(); error.has_value()) {
-                dbgln("Constructed PrettyPrint error: {}", error.value());
-                return;
-            }
+            TRY(decoder.leave());
 
             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));
+            if (tag.class_ != Class::Universal)
+                builder.appendff("[{}] {} {}", type_name(tag.type), static_cast<u8>(tag.kind), kind_name(tag.kind));
             else
-                builder.appendff("[{}] {}", type_name(tag.value().type), kind_name(tag.value().kind));
-            switch (tag.value().kind) {
+                builder.appendff("[{}] {}", type_name(tag.type), kind_name(tag.kind));
+            switch (tag.kind) {
             case Kind::Eol: {
-                auto value = decoder.read<ReadonlyBytes>();
-                if (value.is_error()) {
-                    dbgln("EOL PrettyPrint error: {}", value.error());
-                    return;
-                }
+                TRY(decoder.read<ReadonlyBytes>());
                 break;
             }
             case Kind::Boolean: {
-                auto value = decoder.read<bool>();
-                if (value.is_error()) {
-                    dbgln("Bool PrettyPrint error: {}", value.error());
-                    return;
-                }
-                builder.appendff(" {}", value.value());
+                auto value = TRY(decoder.read<bool>());
+                builder.appendff(" {}", value);
                 break;
             }
             case Kind::Integer: {
-                auto value = decoder.read<ReadonlyBytes>();
-                if (value.is_error()) {
-                    dbgln("Integer PrettyPrint error: {}", value.error());
-                    return;
-                }
+                auto value = TRY(decoder.read<ReadonlyBytes>());
                 builder.append(" 0x"sv);
-                for (auto ch : value.value())
+                for (auto ch : value)
                     builder.appendff("{:0>2x}", ch);
                 break;
             }
             case Kind::BitString: {
-                auto value = decoder.read<BitmapView const>();
-                if (value.is_error()) {
-                    dbgln("BitString PrettyPrint error: {}", value.error());
-                    return;
-                }
+                auto value = TRY(decoder.read<BitmapView>());
                 builder.append(" 0b"sv);
-                for (size_t i = 0; i < value.value().size(); ++i)
-                    builder.append(value.value().get(i) ? '1' : '0');
+                for (size_t i = 0; i < value.size(); ++i)
+                    builder.append(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;
-                }
+                auto value = TRY(decoder.read<StringView>());
                 builder.append(" 0x"sv);
-                for (auto ch : value.value())
+                for (auto ch : 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;
-                }
+                TRY(decoder.read<decltype(nullptr)>());
                 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())
+                auto value = TRY(decoder.read<Vector<int>>());
+                for (auto& id : value)
                     builder.appendff(" {}", id);
                 break;
             }
@@ -333,64 +295,29 @@ void pretty_print(Decoder& decoder, DeprecatedOutputStream& stream, int indent)
             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;
-                }
+                auto value = TRY(decoder.read<StringView>());
                 builder.append(' ');
-                builder.append(value.value());
+                builder.append(value);
                 break;
             }
             case Kind::Utf8String: {
-                auto value = decoder.read<Utf8View>();
-                if (value.is_error()) {
-                    dbgln("UTF8 PrettyPrint error: {}", value.error());
-                    return;
-                }
+                auto value = TRY(decoder.read<Utf8View>());
                 builder.append(' ');
-                for (auto cp : value.value())
+                for (auto cp : value)
                     builder.append_code_point(cp);
                 break;
             }
             case Kind::Sequence:
             case Kind::Set:
-                dbgln("Seq/Sequence PrettyPrint error: Unexpected Primitive");
-                return;
+                return Error::from_string_literal("ASN1::Decoder: Unexpected Primitive");
             }
         }
 
         builder.append('\n');
         stream.write(builder.string_view().bytes());
     }
-}
 
+    return {};
 }
 
-ErrorOr<void> AK::Formatter<Crypto::ASN1::DecodeError>::format(FormatBuilder& fmtbuilder, Crypto::ASN1::DecodeError error)
-{
-    using Crypto::ASN1::DecodeError;
-
-    switch (error) {
-    case DecodeError::NoInput:
-        return fmtbuilder.put_string("DecodeError(No input provided)"sv);
-    case DecodeError::NonConformingType:
-        return fmtbuilder.put_string("DecodeError(Tried to read with a non-conforming type)"sv);
-    case DecodeError::EndOfStream:
-        return fmtbuilder.put_string("DecodeError(End of stream)"sv);
-    case DecodeError::NotEnoughData:
-        return fmtbuilder.put_string("DecodeError(Not enough data)"sv);
-    case DecodeError::EnteringNonConstructedTag:
-        return fmtbuilder.put_string("DecodeError(Tried to enter a primitive tag)"sv);
-    case DecodeError::LeavingMainContext:
-        return fmtbuilder.put_string("DecodeError(Tried to leave the main context)"sv);
-    case DecodeError::InvalidInputFormat:
-        return fmtbuilder.put_string("DecodeError(Input data contained invalid syntax/data)"sv);
-    case DecodeError::Overflow:
-        return fmtbuilder.put_string("DecodeError(Construction would overflow)"sv);
-    case DecodeError::UnsupportedFormat:
-        return fmtbuilder.put_string("DecodeError(Input data format not supported by this parser)"sv);
-    default:
-        return fmtbuilder.put_string("DecodeError(Unknown)"sv);
-    }
 }

+ 27 - 44
Userland/Libraries/LibCrypto/ASN1/DER.h

@@ -14,18 +14,6 @@
 
 namespace Crypto::ASN1 {
 
-enum class DecodeError {
-    NoInput,
-    NonConformingType,
-    EndOfStream,
-    NotEnoughData,
-    EnteringNonConstructedTag,
-    LeavingMainContext,
-    InvalidInputFormat,
-    Overflow,
-    UnsupportedFormat,
-};
-
 class BitStringView {
 public:
     BitStringView(ReadonlyBytes data, size_t unused_bits)
@@ -60,7 +48,7 @@ public:
     }
 
     // Read a tag without consuming it (and its data).
-    Result<Tag, DecodeError> peek();
+    ErrorOr<Tag> peek();
 
     bool eof() const;
 
@@ -70,13 +58,13 @@ public:
         ValueType value;
     };
 
-    Optional<DecodeError> drop()
+    ErrorOr<void> drop()
     {
         if (m_stack.is_empty())
-            return DecodeError::NoInput;
+            return Error::from_string_literal("ASN1::Decoder: Trying to drop using an empty stack");
 
         if (eof())
-            return DecodeError::EndOfStream;
+            return Error::from_string_literal("ASN1::Decoder: Trying to drop using a decoder that is EOF");
 
         auto previous_position = m_stack;
 
@@ -105,13 +93,13 @@ public:
     }
 
     template<typename ValueType>
-    Result<ValueType, DecodeError> read(Optional<Class> class_override = {}, Optional<Kind> kind_override = {})
+    ErrorOr<ValueType> read(Optional<Class> class_override = {}, Optional<Kind> kind_override = {})
     {
         if (m_stack.is_empty())
-            return DecodeError::NoInput;
+            return Error::from_string_literal("ASN1::Decoder: Trying to read using an empty stack");
 
         if (eof())
-            return DecodeError::EndOfStream;
+            return Error::from_string_literal("ASN1::Decoder: Trying to read using a decoder that is EOF");
 
         auto previous_position = m_stack;
 
@@ -141,38 +129,38 @@ public:
         return value_or_error.release_value();
     }
 
-    Optional<DecodeError> enter();
-    Optional<DecodeError> leave();
+    ErrorOr<void> enter();
+    ErrorOr<void> leave();
 
 private:
     template<typename ValueType, typename DecodedType>
-    Result<ValueType, DecodeError> with_type_check(DecodedType&& value)
+    ErrorOr<ValueType> with_type_check(DecodedType&& value)
     {
         if constexpr (requires { ValueType { value }; })
             return ValueType { value };
 
-        return DecodeError::NonConformingType;
+        return Error::from_string_literal("ASN1::Decoder: Trying to decode a value from an incompatible type");
     }
 
     template<typename ValueType, typename DecodedType>
-    Result<ValueType, DecodeError> with_type_check(Result<DecodedType, DecodeError>&& value_or_error)
+    ErrorOr<ValueType> with_type_check(ErrorOr<DecodedType>&& value_or_error)
     {
         if (value_or_error.is_error())
             return value_or_error.error();
 
         if constexpr (IsSame<ValueType, bool> && !IsSame<DecodedType, bool>) {
-            return DecodeError::NonConformingType;
+            return Error::from_string_literal("ASN1::Decoder: Trying to decode a boolean from a non-boolean type");
         } else {
             auto&& value = value_or_error.value();
             if constexpr (requires { ValueType { value }; })
                 return ValueType { value };
         }
 
-        return DecodeError::NonConformingType;
+        return Error::from_string_literal("ASN1::Decoder: Trying to decode a value from an incompatible type");
     }
 
     template<typename ValueType>
-    Result<ValueType, DecodeError> read_value(Class klass, Kind kind, size_t length)
+    ErrorOr<ValueType> read_value(Class klass, Kind kind, size_t length)
     {
         auto data_or_error = read_bytes(length);
         if (data_or_error.is_error())
@@ -209,28 +197,23 @@ private:
         return with_type_check<ValueType>(data);
     }
 
-    Result<Tag, DecodeError> read_tag();
-    Result<size_t, DecodeError> read_length();
-    Result<u8, DecodeError> read_byte();
-    Result<ReadonlyBytes, DecodeError> read_bytes(size_t length);
+    ErrorOr<Tag> read_tag();
+    ErrorOr<size_t> read_length();
+    ErrorOr<u8> read_byte();
+    ErrorOr<ReadonlyBytes> read_bytes(size_t length);
 
-    static Result<bool, DecodeError> decode_boolean(ReadonlyBytes);
-    static Result<UnsignedBigInteger, DecodeError> decode_arbitrary_sized_integer(ReadonlyBytes);
-    static Result<StringView, DecodeError> decode_octet_string(ReadonlyBytes);
-    static Result<nullptr_t, DecodeError> decode_null(ReadonlyBytes);
-    static Result<Vector<int>, DecodeError> decode_object_identifier(ReadonlyBytes);
-    static Result<StringView, DecodeError> decode_printable_string(ReadonlyBytes);
-    static Result<BitStringView, DecodeError> decode_bit_string(ReadonlyBytes);
+    static ErrorOr<bool> decode_boolean(ReadonlyBytes);
+    static ErrorOr<UnsignedBigInteger> decode_arbitrary_sized_integer(ReadonlyBytes);
+    static ErrorOr<StringView> decode_octet_string(ReadonlyBytes);
+    static ErrorOr<nullptr_t> decode_null(ReadonlyBytes);
+    static ErrorOr<Vector<int>> decode_object_identifier(ReadonlyBytes);
+    static ErrorOr<StringView> decode_printable_string(ReadonlyBytes);
+    static ErrorOr<BitStringView> decode_bit_string(ReadonlyBytes);
 
     Vector<ReadonlyBytes> m_stack;
     Optional<Tag> m_current_tag;
 };
 
-void pretty_print(Decoder&, DeprecatedOutputStream&, int indent = 0);
+ErrorOr<void> pretty_print(Decoder&, DeprecatedOutputStream&, int indent = 0);
 
 }
-
-template<>
-struct AK::Formatter<Crypto::ASN1::DecodeError> : Formatter<StringView> {
-    ErrorOr<void> format(FormatBuilder&, Crypto::ASN1::DecodeError);
-};

+ 6 - 6
Userland/Libraries/LibCrypto/PK/RSA.cpp

@@ -47,9 +47,9 @@ RSA::KeyPairType RSA::parse_rsa_key(ReadonlyBytes der)
     // Then enter the sequence
     {
         auto error = decoder.enter();
-        if (error.has_value()) {
+        if (error.is_error()) {
             // Something was weird with the input.
-            dbgln_if(RSA_PARSE_DEBUG, "RSA key parse failed: {}", error.value());
+            dbgln_if(RSA_PARSE_DEBUG, "RSA key parse failed: {}", error.error());
             return keypair;
         }
     }
@@ -74,16 +74,16 @@ RSA::KeyPairType RSA::parse_rsa_key(ReadonlyBytes der)
 
         // It's a sequence, now let's see if it's actually an RSA key.
         auto error = decoder.enter();
-        if (error.has_value()) {
+        if (error.is_error()) {
             // Shenanigans!
-            dbgln_if(RSA_PARSE_DEBUG, "RSA PKCS#8 public key parse failed: {}", error.value());
+            dbgln_if(RSA_PARSE_DEBUG, "RSA PKCS#8 public key parse failed: {}", error.error());
             return false;
         }
 
         ScopeGuard leave { [&] {
             auto error = decoder.leave();
-            if (error.has_value()) {
-                dbgln_if(RSA_PARSE_DEBUG, "RSA key parse failed: {}", error.value());
+            if (error.is_error()) {
+                dbgln_if(RSA_PARSE_DEBUG, "RSA key parse failed: {}", error.error());
                 has_read_error = true;
             }
         } };

+ 6 - 6
Userland/Libraries/LibTLS/Certificate.cpp

@@ -37,8 +37,8 @@ Optional<Certificate> Certificate::parse_asn1(ReadonlyBytes buffer, bool)
 {
 #define ENTER_SCOPE_WITHOUT_TYPECHECK(scope)                                               \
     do {                                                                                   \
-        if (auto result = decoder.enter(); result.has_value()) {                           \
-            dbgln_if(TLS_DEBUG, "Failed to enter object (" scope "): {}", result.value()); \
+        if (auto result = decoder.enter(); result.is_error()) {                            \
+            dbgln_if(TLS_DEBUG, "Failed to enter object (" scope "): {}", result.error()); \
             return {};                                                                     \
         }                                                                                  \
     } while (0)
@@ -59,8 +59,8 @@ Optional<Certificate> Certificate::parse_asn1(ReadonlyBytes buffer, bool)
 
 #define EXIT_SCOPE(scope)                                                                  \
     do {                                                                                   \
-        if (auto error = decoder.leave(); error.has_value()) {                             \
-            dbgln_if(TLS_DEBUG, "Error while exiting scope " scope ": {}", error.value()); \
+        if (auto error = decoder.leave(); error.is_error()) {                              \
+            dbgln_if(TLS_DEBUG, "Error while exiting scope " scope ": {}", error.error()); \
             return {};                                                                     \
         }                                                                                  \
     } while (0)
@@ -88,8 +88,8 @@ Optional<Certificate> Certificate::parse_asn1(ReadonlyBytes buffer, bool)
 
 #define DROP_OBJECT_OR_FAIL(scope)                                        \
     do {                                                                  \
-        if (auto error = decoder.drop(); error.has_value()) {             \
-            dbgln_if(TLS_DEBUG, scope " read failed: {}", error.value()); \
+        if (auto error = decoder.drop(); error.is_error()) {              \
+            dbgln_if(TLS_DEBUG, scope " read failed: {}", error.error()); \
         }                                                                 \
     } while (0)