Add support for CHOICE to client DER encode/decode logic

This commit is contained in:
Camden Dixie O'Brien 2025-02-25 18:17:30 +00:00
parent 046deccc26
commit 18541786e1
2 changed files with 61 additions and 3 deletions

View File

@ -48,6 +48,8 @@ namespace StudySystemClient.Der {
private static Datum decode_datum(uint8 type, uint8[] content) private static Datum decode_datum(uint8 type, uint8[] content)
throws DecodeError { throws DecodeError {
if ((type & 0xc0) == Choice.BASE_TYPE)
return new Choice.from_content(type, content);
switch (type) { switch (type) {
case Boolean.TYPE: case Boolean.TYPE:
return new Boolean.from_content(content); return new Boolean.from_content(content);
@ -262,4 +264,26 @@ namespace StudySystemClient.Der {
return elems.data; 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);
}
}
} }

View File

@ -172,6 +172,14 @@ void main(string[] args) {
test_encode(sequence, expected); 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 * Decoding
*/ */
@ -227,10 +235,10 @@ void main(string[] args) {
}); });
Test.add_func("/decode/sequence/foo,42", () => { Test.add_func("/decode/sequence/foo,42", () => {
var expected_len = 2;
var bytes = new uint8[] { var bytes = new uint8[] {
0x30, 0x08, 0x0c, 0x03, 0x66, 0x6f, 0x6f, 0x02, 0x01, 0x2a 0x30, 0x08, 0x0c, 0x03, 0x66, 0x6f, 0x6f, 0x02, 0x01, 0x2a
}; };
var expected = 2;
Der.Sequence sequence; Der.Sequence sequence;
try { try {
sequence = decode(bytes) as Der.Sequence; sequence = decode(bytes) as Der.Sequence;
@ -245,9 +253,9 @@ void main(string[] args) {
return; return;
} }
Datum[] elems = sequence.value; Datum[] elems = sequence.value;
if (elems.length != expected) { if (elems.length != expected_len) {
Test.message( Test.message(
@"Expected $expected elements, got $(elems.length)"); @"Expected $expected_len elements, got $(elems.length)");
Test.fail(); Test.fail();
return; return;
} }
@ -255,5 +263,31 @@ void main(string[] args) {
test_integer_value(42, elems[1]); 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(); Test.run();
} }