Support ENUMERATED in client DER library

This commit is contained in:
Camden Dixie O'Brien 2025-02-28 00:03:47 +00:00
parent 38ef12fa02
commit 90a6eb3ab4
4 changed files with 110 additions and 57 deletions

View File

@ -6,6 +6,7 @@ namespace StudySystemClient.Der {
} }
private const uint BASE_HEADER_SIZE = 2; private const uint BASE_HEADER_SIZE = 2;
private const uint8 MAX_INT64_BYTES = 8;
public static Datum decode(uint8[] bytes, out uint? size = null) public static Datum decode(uint8[] bytes, out uint? size = null)
throws DecodeError { throws DecodeError {
@ -61,6 +62,8 @@ namespace StudySystemClient.Der {
return new Sequence.from_content(content); return new Sequence.from_content(content);
case Null.TYPE: case Null.TYPE:
return new Null.from_content(content); return new Null.from_content(content);
case Enumerated.TYPE:
return new Enumerated.from_content(content);
default: default:
throw new DecodeError.UNKNOWN_TYPE("Unsupported type: %02x", throw new DecodeError.UNKNOWN_TYPE("Unsupported type: %02x",
type); type);
@ -135,7 +138,6 @@ namespace StudySystemClient.Der {
public class Integer : Datum { public class Integer : Datum {
internal const uint8 TYPE = 0x02; internal const uint8 TYPE = 0x02;
private const uint8 MAX_BYTES = 8;
public int64 value { get; private set; } public int64 value { get; private set; }
@ -150,59 +152,6 @@ namespace StudySystemClient.Der {
content = bytes; content = bytes;
value = decode_int64(content); 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 { public class Utf8String : Datum {
@ -307,4 +256,75 @@ namespace StudySystemClient.Der {
content = bytes; 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;
}
} }

View File

@ -14,7 +14,9 @@ namespace StudySystemClient {
css_provider, css_provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); 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) { } catch (Error e) {
stderr.printf("Failed to initialize: %s\n", e.message); stderr.printf("Failed to initialize: %s\n", e.message);
return; return;

View File

@ -18,8 +18,6 @@ namespace StudySystemClient {
var activities_view = new ActivitiesView(); var activities_view = new ActivitiesView();
set_child(activities_view); set_child(activities_view);
present();
} }
} }
} }

View File

@ -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) { void main(string[] args) {
Test.init(ref args); Test.init(ref args);
@ -184,6 +210,10 @@ void main(string[] args) {
test_encode(new Der.Null(), { 0x05, 0x00 }); test_encode(new Der.Null(), { 0x05, 0x00 });
}); });
Test.add_func("/encode/enumerated/42", () => {
test_encode(new Enumerated(42), {0x0a, 0x01, 0x2a});
});
/* /*
* Decoding * Decoding
*/ */
@ -310,6 +340,9 @@ void main(string[] args) {
} }
}); });
Test.add_func("/decode/enumerated/42", () => {
test_decode_enumerated({0x0a, 0x01, 0x2a}, 42);
});
Test.run(); Test.run();
} }