diff --git a/build.zig b/build.zig index 3576b66..cac537c 100644 --- a/build.zig +++ b/build.zig @@ -49,7 +49,6 @@ pub fn build(b: *std.Build) void { ctx.addTestModule(root_module); ctx.addTestFile("src/packet.zig"); - ctx.addTestFile("src/identity.zig"); } diff --git a/src/crypto.zig b/src/crypto.zig index 679c46d..5027da2 100644 --- a/src/crypto.zig +++ b/src/crypto.zig @@ -54,6 +54,7 @@ pub fn resolveEngine(comptime provider: PartialEngine) Engine { .sha512 = provider.sha512 orelse SHA512.DefaultImplementation, .x25519 = provider.x25519 orelse X25519.DefaultImplementation, }; + } diff --git a/src/crypto/aes.zig b/src/crypto/aes.zig index df886b2..853f39f 100644 --- a/src/crypto/aes.zig +++ b/src/crypto/aes.zig @@ -10,10 +10,6 @@ pub const CBC256_Implementation = struct { // TODO pub const CBC265_DefaultImplementation = struct { - - // Zig stdlib seems to provide no support for AES CBC265 - // It may need some custom implementation or another library - pub fn encrypt(key: *const [32]u8, iv: *const [16]u8, data: *const []u8) !void { _ = key; _ = iv; diff --git a/src/crypto/ed25519.zig b/src/crypto/ed25519.zig index e58c993..2da4bc1 100644 --- a/src/crypto/ed25519.zig +++ b/src/crypto/ed25519.zig @@ -9,34 +9,21 @@ pub const Implementation = struct { }; // TODO -pub fn defaultImplementation() type { +pub const defaultImplementation = struct { - const Ed25519 = @import("std").crypto.sign.Ed25519; - _ = Ed25519; - - // Again, some Ed25519 functions seem to rely on the io module that is not necessarily available on embedded systems - // It may need some custom implementation or other library - - return struct { - - pub fn generateKeys(pubkey_buffer: *[32]u8, privkey_buffer: *[32]u8) !void { - _ = pubkey_buffer; - _ = privkey_buffer; - return error.NotImplemented; - - } + pub fn generateKeys(privkey_buffer: *[32]u8) !void { + _ = privkey_buffer; + } - pub fn sign(key: *const [32]u8, data: *const []const u8, signature_out: *const [64]u8) !void { - _ = key; - _ = data; - _ = signature_out; - return error.NotImplemented; - } + pub fn sign(key: *const [32]u8, data: *const []const u8, signature_out: *const [64]u8) !void { + _ = key; + _ = data; + _ = signature_out; + } - pub fn verify(signature: *const [64]u8, data: *const []const u8) !void { - _ = signature; - _ = data; - return error.NotImplemented; - } - }; -} + pub fn verify(signature: *const [64]u8, data: *const []const u8) !void { + _ = signature; + _ = data; + } + +}; diff --git a/src/crypto/hkdf.zig b/src/crypto/hkdf.zig index f1e9458..5344700 100644 --- a/src/crypto/hkdf.zig +++ b/src/crypto/hkdf.zig @@ -4,6 +4,4 @@ pub const Implementation = struct { pub const defaultImplementation = struct { - const Hkdf = @import("std").crypto.kdf.hkdf.Hkdf; - }; diff --git a/src/crypto/hmac.zig b/src/crypto/hmac.zig index cb096e8..5344700 100644 --- a/src/crypto/hmac.zig +++ b/src/crypto/hmac.zig @@ -4,12 +4,4 @@ pub const Implementation = struct { pub const defaultImplementation = struct { - const Hmac = @import("std").crypto.auth.hmac.Hmac; - - pub fn create(out: []u8, msg: []const u8, key: []const u8) !void { - _ = out; - _ = msg; - _ = key; - return error.NotImplemented; - } }; diff --git a/src/crypto/sha256.zig b/src/crypto/sha256.zig index 70478e0..5344700 100644 --- a/src/crypto/sha256.zig +++ b/src/crypto/sha256.zig @@ -1,18 +1,7 @@ pub const Implementation = struct { - hash: *const fn (buffer: []const u8, out: []u8) void, }; pub const defaultImplementation = struct { - const Sha256 = @import("std").crypto.hash.sha2.Sha256; - - const HASH_LEN = 32; // In bytes - - pub fn hash(buffer: []const u8, out: []u8) !void { - if (out.len < HASH_LEN) { - return error.BufferTooShort; - } - Sha256.hash(buffer, out, .{}); - } }; diff --git a/src/crypto/sha512.zig b/src/crypto/sha512.zig index a69a88d..5344700 100644 --- a/src/crypto/sha512.zig +++ b/src/crypto/sha512.zig @@ -1,18 +1,7 @@ pub const Implementation = struct { - hash: *const fn (buffer: []const u8, out: []u8) void, }; pub const defaultImplementation = struct { - const Sha512 = @import("std").crypto.sha2.Sha512; - - const HASH_LEN = 64; // In bytes - - pub fn hash(buffer: []const u8, out: []u8) !void { - if (out.len < HASH_LEN) { - return error.BufferTooShort; - } - Sha512.hash(buffer, out, .{}); - } }; diff --git a/src/crypto/x25519.zig b/src/crypto/x25519.zig index f3f6607..5344700 100644 --- a/src/crypto/x25519.zig +++ b/src/crypto/x25519.zig @@ -3,9 +3,5 @@ pub const Implementation = struct { }; pub const defaultImplementation = struct { - - const X25519 = @import("std").std.crypto.dh.X25519; - - // One problem, it uses the zig's io module, which is not supported yet as it depends on the target OS - // It may need a custom implementation or some other library + }; diff --git a/src/destination.zig b/src/destination.zig index e62749c..77ea87a 100644 --- a/src/destination.zig +++ b/src/destination.zig @@ -5,14 +5,13 @@ // pub const Type = enum(u2) { - single = 0b0, - group = 0b01, - plain = 0b10, - link = 0b11, + single = 0x00, + group = 0x01, + plain = 0x02, + link = 0x03, }; -// From the reference implementation, seems weird -pub const ProofStrategy = enum(u8) { +pub const ProofStrategy = enum(u2) { prove_none = 0x21, prove_app = 0x22, prove_all = 0x23, @@ -29,31 +28,13 @@ pub const Direction = enum(u2) { out = 0x12, }; -///////////////// Enums +///////////////// Functions // -const Destination = struct { - - name: []const u8, - aspects: [][]const u8, - direction: Direction, - type: Type, +//////// Helper functions +// - //////// Public functions - // - - // TODO - pub fn hash(self: *Destination, destination_buffer: [128]u8) !void { - _ = self; - _ = destination_buffer; - } - - // TODO - pub fn announce() !void {} -}; - - -///////////////// Helper functions +//////// Public functions // ///////////////// Tests diff --git a/src/identity.zig b/src/identity.zig deleted file mode 100644 index dee9100..0000000 --- a/src/identity.zig +++ /dev/null @@ -1,48 +0,0 @@ -///////////////// Imports -// - -const CryptoEngine = @import("crypto.zig").Engine; - -///////////////// Constants -// - -///////////////// Enums -// - -///////////////// Structs -// - -// TODO -pub fn Identity(comptime crypto_engine: CryptoEngine) type { - _ = crypto_engine; - - return struct { - - //////// Fields - // - publicKey: []const u8, - privateKey: []const u8, - signature: []const u8, - hash: []const u8, - - //////// Functions - // - pub fn generate() !Identity { - return .{ - // .privateKey = crypto_engine.ed25519.generateKey(...), - // .signature = crypto_engine.x25519. - }; - } - }; -} - - -///////////////// Helper functions -// - -///////////////// Tests -// - -const std = @import("std"); - -const expect = std.testing.expect; diff --git a/src/packet.zig b/src/packet.zig index 7b465c4..a38294e 100644 --- a/src/packet.zig +++ b/src/packet.zig @@ -1,8 +1,13 @@ -///////////////// Imports +///////////////// Module // -const CryptoEngine = @import("crypto.zig").Engine; -const Destination = @import("destination.zig"); +const Self = @This(); + +header: PacketHeader, +address1: [ADDRESS_SIZE]u8, +address2: [ADDRESS_SIZE]u8, +context: PacketContext, +data: []u8, ///////////////// Constants @@ -32,6 +37,13 @@ pub const PropagationType = enum(u1) { transport = 1 }; +pub const DestinationType = enum(u2) { + single = 0b0, + group = 0b01, + plain = 0b10, + link = 0b11, +}; + pub const PacketType = enum(u2) { data = 0b0, announce = 0b01, @@ -71,89 +83,15 @@ pub const PacketHeader = packed struct { header: HeaderType, context: ContextFlag, propagation: PropagationType, - destination: Destination.Type, + destination: DestinationType, packet: PacketType, hops: u8, }; - -///////////////// Structs +///////////////// Functions // -const Packet = struct { - - const Self = @This(); - - ///////////////// Fields - // - - header: PacketHeader, - address1: [ADDRESS_SIZE]u8, - address2: [ADDRESS_SIZE]u8, - context: PacketContext, - data: []u8, - - - ///////////////// Public functions - // - - pub fn serialize(packet: *const Self, output_buffer: []u8) !usize { - const has_two_addresses = packet.header.header == HeaderType.type2; - - const target_size = getPacketSize(packet.data.len, has_two_addresses); - - if (output_buffer.len < target_size) { - return error.BufferTooShort; - } - - // Write buffer - var offset: usize = 0; - - @memcpy(output_buffer[offset .. offset + @sizeOf(PacketHeader)], asBytes(&packet.header)); - offset += @sizeOf(PacketHeader); - - @memcpy(output_buffer[offset .. offset + ADDRESS_SIZE], asBytes(&packet.address1)); - offset += ADDRESS_SIZE; - if (has_two_addresses) { - @memcpy(output_buffer[offset .. offset + ADDRESS_SIZE], asBytes(&packet.address2)); - offset += ADDRESS_SIZE; - } - - @memcpy(output_buffer[offset .. offset + @sizeOf(PacketContext)], asBytes(&packet.context)); - offset += @sizeOf(PacketContext); - - @memcpy(output_buffer[offset .. offset + packet.data.len], packet.data); - offset += packet.data.len; - - if (target_size != offset) { - return error.InternalError; - } - - return offset; - } - - // Reads the message buffer and builds the corresponding packet struct inside dest_packet - pub fn deserialize(packet: *Self, message_buffer: []u8) !void { - var offset: usize = 0; - - offset = try copyToPacket(&packet.header, message_buffer, offset, @sizeOf(PacketHeader)); - offset = try copyToPacket(&packet.address1, message_buffer, offset, ADDRESS_SIZE); - const has_two_addresses = packet.header.header == HeaderType.type2; - if (has_two_addresses) { - offset = try copyToPacket(&packet.address2, message_buffer, offset, ADDRESS_SIZE); - } - offset = try copyToPacket(&packet.context, message_buffer, offset, @sizeOf(PacketContext)); - offset = try copyToPacket(packet.data, message_buffer, offset, message_buffer.len - offset); - } - -}; - -// pub fn Packet(comptime crypto_engine: CryptoEngine) type { -// return struct {}; -// } - - -///////////////// Helper functions +//////// Helper functions // // Copies serialized data (as a byte array) into any structure type @@ -178,6 +116,58 @@ fn getPacketSize(data_size: usize, has_two_addresses: bool) usize { return res; } +//////// Public functions +// + +pub fn serialize(packet: *const Self, output_buffer: []u8) !usize { + const has_two_addresses = packet.header.header == HeaderType.type2; + + const target_size = getPacketSize(packet.data.len, has_two_addresses); + + if (output_buffer.len < target_size) { + return error.BufferTooShort; + } + + // Write buffer + var offset: usize = 0; + + @memcpy(output_buffer[offset .. offset + @sizeOf(PacketHeader)], asBytes(&packet.header)); + offset += @sizeOf(PacketHeader); + + @memcpy(output_buffer[offset .. offset + ADDRESS_SIZE], asBytes(&packet.address1)); + offset += ADDRESS_SIZE; + if (has_two_addresses) { + @memcpy(output_buffer[offset .. offset + ADDRESS_SIZE], asBytes(&packet.address2)); + offset += ADDRESS_SIZE; + } + + @memcpy(output_buffer[offset .. offset + @sizeOf(PacketContext)], asBytes(&packet.context)); + offset += @sizeOf(PacketContext); + + @memcpy(output_buffer[offset .. offset + packet.data.len], packet.data); + offset += packet.data.len; + + if (target_size != offset) { + return error.InternalError; + } + + return offset; +} + +// Reads the message buffer and builds the corresponding packet struct inside dest_packet +pub fn deserialize(packet: *Self, message_buffer: []u8) !void { + var offset: usize = 0; + + offset = try copyToPacket(&packet.header, message_buffer, offset, @sizeOf(PacketHeader)); + offset = try copyToPacket(&packet.address1, message_buffer, offset, ADDRESS_SIZE); + const has_two_addresses = packet.header.header == HeaderType.type2; + if (has_two_addresses) { + offset = try copyToPacket(&packet.address2, message_buffer, offset, ADDRESS_SIZE); + } + offset = try copyToPacket(&packet.context, message_buffer, offset, @sizeOf(PacketContext)); + offset = try copyToPacket(packet.data, message_buffer, offset, message_buffer.len - offset); +} + ///////////////// Tests // @@ -191,8 +181,8 @@ const asBytes = std.mem.asBytes; // // Serializes the given packet and makes sure the output is correct -fn testPacketSerialization(packet: *const Packet) !void { - const buf_size = comptime @sizeOf(Packet) + MAX_DATA_SIZE; +fn testPacketSerialization(packet: *const Self) !void { + const buf_size = comptime @sizeOf(Self) + MAX_DATA_SIZE; var buf: [buf_size]u8 = undefined; const res: usize = try packet.serialize(&buf); const has_second_address = packet.header.header == HeaderType.type2; @@ -230,7 +220,7 @@ fn headersEql(h1: *const PacketHeader, h2: *const PacketHeader) bool { and h1.hops == h2.hops; } -fn packetsEql(p1: *const Packet, p2: *const Packet) bool { +fn packetsEql(p1: *const Self, p2: *const Self) bool { return headersEql(&p1.header, &p2.header) and memeql(u8, &p1.address1, &p2.address1) and memeql(u8, &p1.address2, &p2.address2) @@ -252,7 +242,7 @@ test "Basic serialization: header type 1, max data size" { .header = HeaderType.type1, .context = ContextFlag.set, .propagation = PropagationType.transport, - .destination = Destination.Type.single, + .destination = DestinationType.single, .packet = PacketType.announce, .hops = 0, }; @@ -260,7 +250,7 @@ test "Basic serialization: header type 1, max data size" { const data_size = MAX_DATA_SIZE; var data: [data_size]u8 = undefined; - const packet: Packet = .{ + const packet: Self = .{ .header = header, .address1 = undefined, .address2 = undefined, @@ -268,7 +258,7 @@ test "Basic serialization: header type 1, max data size" { .data = &data, }; - try testPacketSerialization(&packet); + try packet.testPacketSerialization(); } test "Basic serialization: header type 2, max data size" { @@ -277,7 +267,7 @@ test "Basic serialization: header type 2, max data size" { .header = HeaderType.type2, .context = ContextFlag.set, .propagation = PropagationType.transport, - .destination = Destination.Type.single, + .destination = DestinationType.single, .packet = PacketType.announce, .hops = 0, }; @@ -285,7 +275,7 @@ test "Basic serialization: header type 2, max data size" { const data_size = MAX_DATA_SIZE; var data: [data_size]u8 = undefined; - const packet: Packet = .{ + const packet: Self = .{ .header = header, .address1 = undefined, .address2 = undefined, @@ -293,7 +283,7 @@ test "Basic serialization: header type 2, max data size" { .data = &data, }; - try testPacketSerialization(&packet); + try packet.testPacketSerialization(); } test "Basic serialization: header type 1, medium data size" { @@ -302,7 +292,7 @@ test "Basic serialization: header type 1, medium data size" { .header = HeaderType.type1, .context = ContextFlag.set, .propagation = PropagationType.transport, - .destination = Destination.Type.single, + .destination = DestinationType.single, .packet = PacketType.announce, .hops = 0, }; @@ -310,7 +300,7 @@ test "Basic serialization: header type 1, medium data size" { const data_size = MAX_DATA_SIZE / 2 + 3; var data: [data_size]u8 = undefined; - const packet: Packet = .{ + const packet: Self = .{ .header = header, .address1 = undefined, .address2 = undefined, @@ -318,7 +308,7 @@ test "Basic serialization: header type 1, medium data size" { .data = &data, }; - try testPacketSerialization(&packet); + try packet.testPacketSerialization(); } test "Basic serialization: header type 2, medium data size" { @@ -327,7 +317,7 @@ test "Basic serialization: header type 2, medium data size" { .header = HeaderType.type2, .context = ContextFlag.set, .propagation = PropagationType.transport, - .destination = Destination.Type.single, + .destination = DestinationType.single, .packet = PacketType.announce, .hops = 0, }; @@ -335,7 +325,7 @@ test "Basic serialization: header type 2, medium data size" { const data_size = MAX_DATA_SIZE / 2 + 3; var data: [data_size]u8 = undefined; - const packet: Packet = .{ + const packet: Self = .{ .header = header, .address1 = undefined, .address2 = undefined, @@ -343,7 +333,7 @@ test "Basic serialization: header type 2, medium data size" { .data = &data, }; - try testPacketSerialization(&packet); + try packet.testPacketSerialization(); } test "Serialize / Deserialize Packet: Header type2, Medium data size" { @@ -352,7 +342,7 @@ test "Serialize / Deserialize Packet: Header type2, Medium data size" { .header = HeaderType.type2, .context = ContextFlag.set, .propagation = PropagationType.transport, - .destination = Destination.Type.single, + .destination = DestinationType.single, .packet = PacketType.announce, .hops = 0, }; @@ -360,7 +350,7 @@ test "Serialize / Deserialize Packet: Header type2, Medium data size" { const data_size = MAX_DATA_SIZE / 2 + 3; var data: [data_size]u8 = undefined; - const packet: Packet = .{ + const packet: Self = .{ .header = header, .address1 = undefined, .address2 = undefined, @@ -370,7 +360,7 @@ test "Serialize / Deserialize Packet: Header type2, Medium data size" { const buf_size = comptime @sizeOf(PacketHeader) + 2*ADDRESS_SIZE + @sizeOf(PacketContext) + data_size; var buf: [buf_size]u8 = undefined; - var res_packet: Packet = undefined; + var res_packet: Self = undefined; var res_data: [data_size]u8 = undefined; res_packet.data = &res_data; _ = try packet.serialize(&buf); diff --git a/src/root.zig b/src/root.zig index 0dc2d60..9ab6784 100644 --- a/src/root.zig +++ b/src/root.zig @@ -4,10 +4,10 @@ const crypto = @import("crypto.zig"); // You can pass your own cryptographic functions to take advantage of your // platform or use the library's software implementations for compatibility // Use its return value to access the library modules -pub fn RnsZero(comptime crypto_provider: crypto.PartialEngine) type { - const crypto_engine = crypto.resolveEngine(crypto_provider); +pub fn RnsZero(comptime cryptoProvider: crypto.PartialEngine) type { + const cryptoEngine = crypto.resolveEngine(cryptoProvider); + _ = cryptoEngine; return struct { pub const packet = @import("packet.zig"); - pub const identity = @import("identity.zig").Identity(crypto_engine); }; }