From 18541786e1c7484fa108f1197de5c4dcabe4046c Mon Sep 17 00:00:00 2001 From: Camden Dixie O'Brien Date: Tue, 25 Feb 2025 18:17:30 +0000 Subject: [PATCH] Add support for CHOICE to client DER encode/decode logic --- client/src/der.vala | 24 ++++++++++++++++++++++ client/tests/der_tests.vala | 40 ++++++++++++++++++++++++++++++++++--- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/client/src/der.vala b/client/src/der.vala index bfdcfd9..968a0e7 100644 --- a/client/src/der.vala +++ b/client/src/der.vala @@ -48,6 +48,8 @@ namespace StudySystemClient.Der { private static Datum decode_datum(uint8 type, uint8[] content) throws DecodeError { + if ((type & 0xc0) == Choice.BASE_TYPE) + return new Choice.from_content(type, content); switch (type) { case Boolean.TYPE: return new Boolean.from_content(content); @@ -262,4 +264,26 @@ namespace StudySystemClient.Der { return elems.data; } } + + public class Choice : Datum { + internal const uint8 BASE_TYPE = 0x80; + + public int id { get; private set; } + public Datum value { get; private set; } + + public Choice(int id, Datum val) { + type = BASE_TYPE | id; + content = val.encode(); + this.id = id; + value = val; + } + + internal Choice.from_content(uint8 type, uint8[] bytes) + throws DecodeError { + this.type = type; + content = bytes; + id = type & 0x3f; + value = decode(bytes); + } + } } diff --git a/client/tests/der_tests.vala b/client/tests/der_tests.vala index ec9433a..da564a0 100644 --- a/client/tests/der_tests.vala +++ b/client/tests/der_tests.vala @@ -172,6 +172,14 @@ void main(string[] args) { test_encode(sequence, expected); }); + Test.add_func("/encode/choice/1:foo", () => { + var choice = new Der.Choice(1, new Utf8String("foo")); + var expected = new uint8[] { + 0x81, 0x05, 0x0c, 0x03, 0x66, 0x6f, 0x6f + }; + test_encode(choice, expected); + }); + /* * Decoding */ @@ -227,10 +235,10 @@ void main(string[] args) { }); Test.add_func("/decode/sequence/foo,42", () => { + var expected_len = 2; var bytes = new uint8[] { 0x30, 0x08, 0x0c, 0x03, 0x66, 0x6f, 0x6f, 0x02, 0x01, 0x2a }; - var expected = 2; Der.Sequence sequence; try { sequence = decode(bytes) as Der.Sequence; @@ -245,9 +253,9 @@ void main(string[] args) { return; } Datum[] elems = sequence.value; - if (elems.length != expected) { + if (elems.length != expected_len) { Test.message( - @"Expected $expected elements, got $(elems.length)"); + @"Expected $expected_len elements, got $(elems.length)"); Test.fail(); return; } @@ -255,5 +263,31 @@ void main(string[] args) { test_integer_value(42, elems[1]); }); + Test.add_func("/decode/choice/1:foo", () => { + var expected_id = 1; + var bytes = new uint8[] { + 0x81, 0x05, 0x0c, 0x03, 0x66, 0x6f, 0x6f + }; + Der.Choice choice; + try { + choice = decode(bytes) as Der.Choice; + } catch (DecodeError err) { + Test.message("Decoding failed: %s", err.message); + Test.fail(); + return; + } + if (choice == null) { + Test.message("Bytes were not decoded as a CHOICE"); + Test.fail(); + return; + } + if (choice.id != expected_id) { + Test.message(@"Expected ID $expected_id, got $(choice.id)"); + Test.fail(); + return; + } + test_utf8string_value("foo", choice.value); + }); + Test.run(); }