DER.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * Copyright (c) 2020, Ali Mohammad Pur <mpfard@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/BitmapView.h>
  8. #include <AK/Result.h>
  9. #include <AK/Types.h>
  10. #include <LibCrypto/ASN1/ASN1.h>
  11. #include <LibCrypto/BigInt/UnsignedBigInteger.h>
  12. namespace Crypto::ASN1 {
  13. enum class DecodeError {
  14. NoInput,
  15. NonConformingType,
  16. EndOfStream,
  17. NotEnoughData,
  18. EnteringNonConstructedTag,
  19. LeavingMainContext,
  20. InvalidInputFormat,
  21. Overflow,
  22. UnsupportedFormat,
  23. };
  24. class Decoder {
  25. public:
  26. Decoder(ReadonlyBytes data)
  27. {
  28. m_stack.append(data);
  29. }
  30. // Read a tag without consuming it (and its data).
  31. Result<Tag, DecodeError> peek();
  32. bool eof() const;
  33. template<typename ValueType>
  34. struct TaggedValue {
  35. Tag tag;
  36. ValueType value;
  37. };
  38. Optional<DecodeError> drop()
  39. {
  40. if (m_stack.is_empty())
  41. return DecodeError::NoInput;
  42. if (eof())
  43. return DecodeError::EndOfStream;
  44. auto previous_position = m_stack;
  45. auto tag_or_error = peek();
  46. if (tag_or_error.is_error()) {
  47. m_stack = move(previous_position);
  48. return tag_or_error.error();
  49. }
  50. auto length_or_error = read_length();
  51. if (length_or_error.is_error()) {
  52. m_stack = move(previous_position);
  53. return length_or_error.error();
  54. }
  55. auto length = length_or_error.value();
  56. auto bytes_result = read_bytes(length);
  57. if (bytes_result.is_error()) {
  58. m_stack = move(previous_position);
  59. return bytes_result.error();
  60. }
  61. m_current_tag.clear();
  62. return {};
  63. }
  64. template<typename ValueType>
  65. Result<ValueType, DecodeError> read(Optional<Class> class_override = {}, Optional<Kind> kind_override = {})
  66. {
  67. if (m_stack.is_empty())
  68. return DecodeError::NoInput;
  69. if (eof())
  70. return DecodeError::EndOfStream;
  71. auto previous_position = m_stack;
  72. auto tag_or_error = peek();
  73. if (tag_or_error.is_error()) {
  74. m_stack = move(previous_position);
  75. return tag_or_error.error();
  76. }
  77. auto length_or_error = read_length();
  78. if (length_or_error.is_error()) {
  79. m_stack = move(previous_position);
  80. return length_or_error.error();
  81. }
  82. auto tag = tag_or_error.value();
  83. auto length = length_or_error.value();
  84. auto value_or_error = read_value<ValueType>(class_override.value_or(tag.class_), kind_override.value_or(tag.kind), length);
  85. if (value_or_error.is_error()) {
  86. m_stack = move(previous_position);
  87. return value_or_error.error();
  88. }
  89. m_current_tag.clear();
  90. return value_or_error.release_value();
  91. }
  92. Optional<DecodeError> enter();
  93. Optional<DecodeError> leave();
  94. private:
  95. template<typename ValueType, typename DecodedType>
  96. Result<ValueType, DecodeError> with_type_check(DecodedType&& value)
  97. {
  98. if constexpr (requires { ValueType { value }; })
  99. return ValueType { value };
  100. return DecodeError::NonConformingType;
  101. }
  102. template<typename ValueType, typename DecodedType>
  103. Result<ValueType, DecodeError> with_type_check(Result<DecodedType, DecodeError>&& value_or_error)
  104. {
  105. if (value_or_error.is_error())
  106. return value_or_error.error();
  107. if constexpr (IsSame<ValueType, bool> && !IsSame<DecodedType, bool>) {
  108. return DecodeError::NonConformingType;
  109. } else {
  110. auto&& value = value_or_error.value();
  111. if constexpr (requires { ValueType { value }; })
  112. return ValueType { value };
  113. }
  114. return DecodeError::NonConformingType;
  115. }
  116. template<typename ValueType>
  117. Result<ValueType, DecodeError> read_value(Class klass, Kind kind, size_t length)
  118. {
  119. auto data_or_error = read_bytes(length);
  120. if (data_or_error.is_error())
  121. return data_or_error.error();
  122. auto data = data_or_error.value();
  123. if (klass != Class::Universal)
  124. return with_type_check<ValueType>(data);
  125. if (kind == Kind::Boolean)
  126. return with_type_check<ValueType>(decode_boolean(data));
  127. if (kind == Kind::Integer)
  128. return with_type_check<ValueType>(decode_arbitrary_sized_integer(data));
  129. if (kind == Kind::OctetString)
  130. return with_type_check<ValueType>(decode_octet_string(data));
  131. if (kind == Kind::Null)
  132. return with_type_check<ValueType>(decode_null(data));
  133. if (kind == Kind::ObjectIdentifier)
  134. return with_type_check<ValueType>(decode_object_identifier(data));
  135. if (kind == Kind::PrintableString || kind == Kind::IA5String || kind == Kind::UTCTime)
  136. return with_type_check<ValueType>(decode_printable_string(data));
  137. if (kind == Kind::Utf8String)
  138. return with_type_check<ValueType>(StringView { data.data(), data.size() });
  139. if (kind == Kind::BitString)
  140. return with_type_check<ValueType>(decode_bit_string(data));
  141. return with_type_check<ValueType>(data);
  142. }
  143. Result<Tag, DecodeError> read_tag();
  144. Result<size_t, DecodeError> read_length();
  145. Result<u8, DecodeError> read_byte();
  146. Result<ReadonlyBytes, DecodeError> read_bytes(size_t length);
  147. static Result<bool, DecodeError> decode_boolean(ReadonlyBytes);
  148. static Result<UnsignedBigInteger, DecodeError> decode_arbitrary_sized_integer(ReadonlyBytes);
  149. static Result<StringView, DecodeError> decode_octet_string(ReadonlyBytes);
  150. static Result<std::nullptr_t, DecodeError> decode_null(ReadonlyBytes);
  151. static Result<Vector<int>, DecodeError> decode_object_identifier(ReadonlyBytes);
  152. static Result<StringView, DecodeError> decode_printable_string(ReadonlyBytes);
  153. static Result<const BitmapView, DecodeError> decode_bit_string(ReadonlyBytes);
  154. Vector<ReadonlyBytes> m_stack;
  155. Optional<Tag> m_current_tag;
  156. };
  157. void pretty_print(Decoder&, OutputStream&, int indent = 0);
  158. }
  159. template<>
  160. struct AK::Formatter<Crypto::ASN1::DecodeError> : Formatter<StringView> {
  161. void format(FormatBuilder&, Crypto::ASN1::DecodeError);
  162. };