From 90a6eb3ab4bc7216275ca67f69937ba51cd3f803 Mon Sep 17 00:00:00 2001 From: Camden Dixie O'Brien Date: Fri, 28 Feb 2025 00:03:47 +0000 Subject: [PATCH] Support ENUMERATED in client DER library --- client/src/der.vala | 128 +++++++++++++++++++++--------------- client/src/main.vala | 4 +- client/src/main_window.vala | 2 - client/tests/der_tests.vala | 33 ++++++++++ 4 files changed, 110 insertions(+), 57 deletions(-) diff --git a/client/src/der.vala b/client/src/der.vala index 63753e6..184db40 100644 --- a/client/src/der.vala +++ b/client/src/der.vala @@ -6,6 +6,7 @@ namespace StudySystemClient.Der { } private const uint BASE_HEADER_SIZE = 2; + private const uint8 MAX_INT64_BYTES = 8; public static Datum decode(uint8[] bytes, out uint? size = null) throws DecodeError { @@ -61,6 +62,8 @@ namespace StudySystemClient.Der { return new Sequence.from_content(content); case Null.TYPE: return new Null.from_content(content); + case Enumerated.TYPE: + return new Enumerated.from_content(content); default: throw new DecodeError.UNKNOWN_TYPE("Unsupported type: %02x", type); @@ -135,7 +138,6 @@ namespace StudySystemClient.Der { public class Integer : Datum { internal const uint8 TYPE = 0x02; - private const uint8 MAX_BYTES = 8; public int64 value { get; private set; } @@ -150,59 +152,6 @@ namespace StudySystemClient.Der { content = bytes; value = decode_int64(content); } - - private static uint64 twos_complement(uint64 x) { - return ~x + 1; - } - - private static int min_bits(bool negative, uint64 x) { - int n = 0; - if (negative) { - while ((x >> (n + 8) & 0xff) != 0xff) - n += 8; - } else { - while (x >> (n + 8) > 0) - n += 8; - } - return n; - } - - private static uint8[] encode_int64(int64 val) { - var negative = val < 0; - var uval = negative ? twos_complement(val.abs()) : val; - var shift = min_bits(negative, uval); - - var buffer = new ByteArray(); - for (; shift >= 0; shift -= 8) - buffer.append({(uint8)(uval >> shift)}); - - if (!negative && (buffer.data[0] & 0x80) != 0) - buffer.prepend({0x00}); - - return buffer.data; - } - - private static int64 decode_int64(uint8[] bytes) throws DecodeError { - if (bytes.length > MAX_BYTES) { - throw new DecodeError.INVALID_CONTENT( - "int64 too small for %u bytes", bytes.length); - } - var negative = (bytes[0] & 0x80) != 0; - var val = decode_start_val(negative, bytes.length); - foreach (var byte in bytes) - val = val << 8 | byte; - return negative ? -(int64)twos_complement(val) : (int64)val; - } - - private static uint64 decode_start_val(bool negative, uint length) - { - if (!negative) - return 0; - var val = 0; - for (uint i = 0; i < MAX_BYTES - length; ++i) - val = val << 8 | 0xff; - return val; - } } public class Utf8String : Datum { @@ -307,4 +256,75 @@ namespace StudySystemClient.Der { content = bytes; } } + + public class Enumerated : Datum { + internal const uint8 TYPE = 0x0a; + + public int64 value { get; private set; } + + public Enumerated(int64 val) { + type = TYPE; + content = encode_int64(val); + value = val; + } + + internal Enumerated.from_content(uint8[] bytes) throws DecodeError { + type = TYPE; + content = bytes; + value = decode_int64(content); + } + } + + private static uint64 twos_complement(uint64 x) { + return ~x + 1; + } + + private static int min_bits(bool negative, uint64 x) { + int n = 0; + if (negative) { + while ((x >> (n + 8) & 0xff) != 0xff) + n += 8; + } else { + while (x >> (n + 8) > 0) + n += 8; + } + return n; + } + + private static uint8[] encode_int64(int64 val) { + var negative = val < 0; + var uval = negative ? twos_complement(val.abs()) : val; + var shift = min_bits(negative, uval); + + var buffer = new ByteArray(); + for (; shift >= 0; shift -= 8) + buffer.append({(uint8)(uval >> shift)}); + + if (!negative && (buffer.data[0] & 0x80) != 0) + buffer.prepend({0x00}); + + return buffer.data; + } + + private static int64 decode_int64(uint8[] bytes) throws DecodeError { + if (bytes.length > MAX_INT64_BYTES) { + throw new DecodeError.INVALID_CONTENT( + "int64 too small for %u bytes", bytes.length); + } + var negative = (bytes[0] & 0x80) != 0; + var val = decode_start_val(negative, bytes.length); + foreach (var byte in bytes) + val = val << 8 | byte; + return negative ? -(int64)twos_complement(val) : (int64)val; + } + + private static uint64 decode_start_val(bool negative, uint length) + { + if (!negative) + return 0; + var val = 0; + for (uint i = 0; i < MAX_INT64_BYTES - length; ++i) + val = val << 8 | 0xff; + return val; + } } diff --git a/client/src/main.vala b/client/src/main.vala index a3dca6b..0200f9f 100644 --- a/client/src/main.vala +++ b/client/src/main.vala @@ -14,7 +14,9 @@ namespace StudySystemClient { css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - new MainWindow(this, new Connection(Config.CERT_DIR)); + var connection = new Connection(Config.CERT_DIR); + var main_window = new MainWindow(this, connection); + main_window.present(); } catch (Error e) { stderr.printf("Failed to initialize: %s\n", e.message); return; diff --git a/client/src/main_window.vala b/client/src/main_window.vala index 9eeede7..14f3de1 100644 --- a/client/src/main_window.vala +++ b/client/src/main_window.vala @@ -18,8 +18,6 @@ namespace StudySystemClient { var activities_view = new ActivitiesView(); set_child(activities_view); - - present(); } } } diff --git a/client/tests/der_tests.vala b/client/tests/der_tests.vala index f3f2388..aeb75c7 100644 --- a/client/tests/der_tests.vala +++ b/client/tests/der_tests.vala @@ -98,6 +98,32 @@ static void test_utf8string_value(string expected, Datum datum) { } } +static void test_decode_enumerated(uint8[] bytes, int64 expected) { + Datum datum; + try { + datum = decode(bytes); + } catch (DecodeError err) { + Test.message("Decoding failed: %s", err.message); + Test.fail(); + return; + } + test_enumerated_value(expected, datum); +} + +static void test_enumerated_value(int64 expected, Datum datum) { + var enumerated = datum as Enumerated; + if (enumerated == null) { + Test.message("Bytes were not decoded as an ENUMERATED"); + Test.fail(); + return; + } + if (enumerated.value != expected) { + Test.message(@"Expected $expected got $(enumerated.value)"); + Test.fail(); + return; + } +} + void main(string[] args) { Test.init(ref args); @@ -184,6 +210,10 @@ void main(string[] args) { test_encode(new Der.Null(), { 0x05, 0x00 }); }); + Test.add_func("/encode/enumerated/42", () => { + test_encode(new Enumerated(42), {0x0a, 0x01, 0x2a}); + }); + /* * Decoding */ @@ -310,6 +340,9 @@ void main(string[] args) { } }); + Test.add_func("/decode/enumerated/42", () => { + test_decode_enumerated({0x0a, 0x01, 0x2a}, 42); + }); Test.run(); }