ASN1.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. * Copyright (c) 2021, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibCrypto/ASN1/ASN1.h>
  7. namespace Crypto::ASN1 {
  8. String kind_name(Kind kind)
  9. {
  10. switch (kind) {
  11. case Kind::Eol:
  12. return "EndOfList";
  13. case Kind::Boolean:
  14. return "Boolean";
  15. case Kind::Integer:
  16. return "Integer";
  17. case Kind::BitString:
  18. return "BitString";
  19. case Kind::OctetString:
  20. return "OctetString";
  21. case Kind::Null:
  22. return "Null";
  23. case Kind::ObjectIdentifier:
  24. return "ObjectIdentifier";
  25. case Kind::IA5String:
  26. return "IA5String";
  27. case Kind::PrintableString:
  28. return "PrintableString";
  29. case Kind::Utf8String:
  30. return "UTF8String";
  31. case Kind::UTCTime:
  32. return "UTCTime";
  33. case Kind::GeneralizedTime:
  34. return "GeneralizedTime";
  35. case Kind::Sequence:
  36. return "Sequence";
  37. case Kind::Set:
  38. return "Set";
  39. }
  40. return "InvalidKind";
  41. }
  42. String class_name(Class class_)
  43. {
  44. switch (class_) {
  45. case Class::Application:
  46. return "Application";
  47. case Class::Context:
  48. return "Context";
  49. case Class::Private:
  50. return "Private";
  51. case Class::Universal:
  52. return "Universal";
  53. }
  54. return "InvalidClass";
  55. }
  56. String type_name(Type type)
  57. {
  58. switch (type) {
  59. case Type::Constructed:
  60. return "Constructed";
  61. case Type::Primitive:
  62. return "Primitive";
  63. }
  64. return "InvalidType";
  65. }
  66. Optional<Core::DateTime> parse_utc_time(const StringView& time)
  67. {
  68. // YYMMDDhhmm[ss]Z or YYMMDDhhmm[ss](+|-)hhmm
  69. GenericLexer lexer(time);
  70. auto year_in_century = lexer.consume(2).to_uint();
  71. auto month = lexer.consume(2).to_uint();
  72. auto day = lexer.consume(2).to_uint();
  73. auto hour = lexer.consume(2).to_uint();
  74. auto minute = lexer.consume(2).to_uint();
  75. Optional<unsigned> seconds, offset_hours, offset_minutes;
  76. [[maybe_unused]] bool negative_offset = false;
  77. if (!lexer.next_is('Z')) {
  78. if (!lexer.next_is(is_any_of("+-"))) {
  79. seconds = lexer.consume(2).to_uint();
  80. if (!seconds.has_value()) {
  81. return {};
  82. }
  83. }
  84. if (lexer.next_is(is_any_of("+-"))) {
  85. negative_offset = lexer.consume() == '-';
  86. offset_hours = lexer.consume(2).to_uint();
  87. offset_minutes = lexer.consume(2).to_uint();
  88. if (!offset_hours.has_value() || !offset_minutes.has_value()) {
  89. return {};
  90. }
  91. } else {
  92. lexer.consume();
  93. }
  94. } else {
  95. lexer.consume();
  96. }
  97. if (!year_in_century.has_value() || !month.has_value() || !day.has_value() || !hour.has_value() || !minute.has_value()) {
  98. return {};
  99. }
  100. auto full_year = (Core::DateTime::now().year() / 100) * 100 + year_in_century.value();
  101. auto full_seconds = seconds.value_or(0);
  102. // FIXME: Handle offsets!
  103. if (offset_hours.has_value() || offset_minutes.has_value())
  104. dbgln("FIXME: Implement UTCTime with offset!");
  105. return Core::DateTime::create(full_year, month.value(), day.value(), hour.value(), minute.value(), full_seconds);
  106. }
  107. Optional<Core::DateTime> parse_generalized_time(const StringView& time)
  108. {
  109. // YYYYMMDDhh[mm[ss[.fff]]] or YYYYMMDDhh[mm[ss[.fff]]]Z or YYYYMMDDhh[mm[ss[.fff]]](+|-)hhmm
  110. GenericLexer lexer(time);
  111. auto year = lexer.consume(4).to_uint();
  112. auto month = lexer.consume(2).to_uint();
  113. auto day = lexer.consume(2).to_uint();
  114. auto hour = lexer.consume(2).to_uint();
  115. Optional<unsigned> minute, seconds, milliseconds, offset_hours, offset_minutes;
  116. [[maybe_unused]] bool negative_offset = false;
  117. if (!lexer.is_eof()) {
  118. if (lexer.consume_specific('Z'))
  119. goto done_parsing;
  120. if (!lexer.next_is(is_any_of("+-"))) {
  121. minute = lexer.consume(2).to_uint();
  122. if (!minute.has_value()) {
  123. return {};
  124. }
  125. if (lexer.consume_specific('Z'))
  126. goto done_parsing;
  127. }
  128. if (!lexer.next_is(is_any_of("+-"))) {
  129. seconds = lexer.consume(2).to_uint();
  130. if (!seconds.has_value()) {
  131. return {};
  132. }
  133. if (lexer.consume_specific('Z'))
  134. goto done_parsing;
  135. }
  136. if (lexer.consume_specific('.')) {
  137. milliseconds = lexer.consume(3).to_uint();
  138. if (!milliseconds.has_value()) {
  139. return {};
  140. }
  141. if (lexer.consume_specific('Z'))
  142. goto done_parsing;
  143. }
  144. if (lexer.next_is(is_any_of("+-"))) {
  145. negative_offset = lexer.consume() == '-';
  146. offset_hours = lexer.consume(2).to_uint();
  147. offset_minutes = lexer.consume(2).to_uint();
  148. if (!offset_hours.has_value() || !offset_minutes.has_value()) {
  149. return {};
  150. }
  151. } else {
  152. lexer.consume();
  153. }
  154. }
  155. done_parsing:;
  156. if (!year.has_value() || !month.has_value() || !day.has_value() || !hour.has_value()) {
  157. return {};
  158. }
  159. // FIXME: Handle offsets!
  160. if (offset_hours.has_value() || offset_minutes.has_value())
  161. dbgln("FIXME: Implement GeneralizedTime with offset!");
  162. // Unceremonially drop the milliseconds on the floor.
  163. return Core::DateTime::create(year.value(), month.value(), day.value(), hour.value(), minute.value_or(0), seconds.value_or(0));
  164. }
  165. }