From 13abbc5ea8c6b0bb145983c7d232dbe3bdc398c3 Mon Sep 17 00:00:00 2001 From: AnotherTest Date: Sun, 18 Apr 2021 13:44:36 +0430 Subject: [PATCH] LibCrypto: Implement UTCTime and GeneralizedTime parsers --- Userland/Libraries/LibCrypto/ASN1/ASN1.cpp | 114 +++++++++++++++++++++ Userland/Libraries/LibCrypto/ASN1/ASN1.h | 4 + 2 files changed, 118 insertions(+) diff --git a/Userland/Libraries/LibCrypto/ASN1/ASN1.cpp b/Userland/Libraries/LibCrypto/ASN1/ASN1.cpp index 17d9c68a65..250b106fac 100644 --- a/Userland/Libraries/LibCrypto/ASN1/ASN1.cpp +++ b/Userland/Libraries/LibCrypto/ASN1/ASN1.cpp @@ -92,4 +92,118 @@ String type_name(Type type) return "InvalidType"; } +Optional parse_utc_time(const StringView& time) +{ + // YYMMDDhhmm[ss]Z or YYMMDDhhmm[ss](+|-)hhmm + GenericLexer lexer(time); + auto year_in_century = lexer.consume(2).to_uint(); + auto month = lexer.consume(2).to_uint(); + auto day = lexer.consume(2).to_uint(); + auto hour = lexer.consume(2).to_uint(); + auto minute = lexer.consume(2).to_uint(); + Optional seconds, offset_hours, offset_minutes; + [[maybe_unused]] bool negative_offset = false; + if (!lexer.next_is('Z')) { + if (!lexer.next_is(is_any_of("+-"))) { + seconds = lexer.consume(2).to_uint(); + if (!seconds.has_value()) { + return {}; + } + } + + if (lexer.next_is(is_any_of("+-"))) { + negative_offset = lexer.consume() == '-'; + offset_hours = lexer.consume(2).to_uint(); + offset_minutes = lexer.consume(2).to_uint(); + if (!offset_hours.has_value() || !offset_minutes.has_value()) { + return {}; + } + } else { + lexer.consume(); + } + } else { + lexer.consume(); + } + + if (!year_in_century.has_value() || !month.has_value() || !day.has_value() || !hour.has_value() || !minute.has_value()) { + return {}; + } + + auto full_year = (Core::DateTime::now().year() / 100) * 100 + year_in_century.value(); + auto full_seconds = seconds.value_or(0); + + // FIXME: Handle offsets! + if (offset_hours.has_value() || offset_minutes.has_value()) + dbgln("FIXME: Implement UTCTime with offset!"); + + return Core::DateTime::create(full_year, month.value(), day.value(), hour.value(), minute.value(), full_seconds); +} + +Optional parse_generalized_time(const StringView& time) +{ + // YYYYMMDDhh[mm[ss[.fff]]] or YYYYMMDDhh[mm[ss[.fff]]]Z or YYYYMMDDhh[mm[ss[.fff]]](+|-)hhmm + GenericLexer lexer(time); + auto year = lexer.consume(4).to_uint(); + auto month = lexer.consume(2).to_uint(); + auto day = lexer.consume(2).to_uint(); + auto hour = lexer.consume(2).to_uint(); + Optional minute, seconds, miliseconds, offset_hours, offset_minutes; + [[maybe_unused]] bool negative_offset = false; + if (!lexer.is_eof()) { + if (lexer.consume_specific('Z')) + goto done_parsing; + + if (!lexer.next_is(is_any_of("+-"))) { + minute = lexer.consume(2).to_uint(); + if (!minute.has_value()) { + return {}; + } + if (lexer.consume_specific('Z')) + goto done_parsing; + } + + if (!lexer.next_is(is_any_of("+-"))) { + seconds = lexer.consume(2).to_uint(); + if (!seconds.has_value()) { + return {}; + } + if (lexer.consume_specific('Z')) + goto done_parsing; + } + + if (lexer.consume_specific('.')) { + miliseconds = lexer.consume(3).to_uint(); + if (!miliseconds.has_value()) { + return {}; + } + if (lexer.consume_specific('Z')) + goto done_parsing; + } + + if (lexer.next_is(is_any_of("+-"))) { + negative_offset = lexer.consume() == '-'; + offset_hours = lexer.consume(2).to_uint(); + offset_minutes = lexer.consume(2).to_uint(); + if (!offset_hours.has_value() || !offset_minutes.has_value()) { + return {}; + } + } else { + lexer.consume(); + } + } + +done_parsing:; + + if (!year.has_value() || !month.has_value() || !day.has_value() || !hour.has_value()) { + return {}; + } + + // FIXME: Handle offsets! + if (offset_hours.has_value() || offset_minutes.has_value()) + dbgln("FIXME: Implement GeneralizedTime with offset!"); + + // Unceremonially drop the miliseconds on the floor. + return Core::DateTime::create(year.value(), month.value(), day.value(), hour.value(), minute.value_or(0), seconds.value_or(0)); +} + } diff --git a/Userland/Libraries/LibCrypto/ASN1/ASN1.h b/Userland/Libraries/LibCrypto/ASN1/ASN1.h index 6b7d805b56..64ff41b58f 100644 --- a/Userland/Libraries/LibCrypto/ASN1/ASN1.h +++ b/Userland/Libraries/LibCrypto/ASN1/ASN1.h @@ -27,6 +27,7 @@ #pragma once #include +#include #include namespace Crypto::ASN1 { @@ -71,4 +72,7 @@ String kind_name(Kind); String class_name(Class); String type_name(Type); +Optional parse_utc_time(const StringView&); +Optional parse_generalized_time(const StringView&); + }