Support ENUMERATED in client DER library
This commit is contained in:
parent
38ef12fa02
commit
90a6eb3ab4
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -18,8 +18,6 @@ namespace StudySystemClient {
|
||||
|
||||
var activities_view = new ActivitiesView();
|
||||
set_child(activities_view);
|
||||
|
||||
present();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user