Compare commits

..

No commits in common. "1216dc2282f4bed843e04b207d4ebb372e7cb885" and "cb72a9cdc9c9160ee755dd6f70162fb78a7b2a14" have entirely different histories.

13 changed files with 117 additions and 247 deletions

View file

@ -49,7 +49,6 @@ pub fn build(b: *std.Build) void {
ctx.addTestModule(root_module); ctx.addTestModule(root_module);
ctx.addTestFile("src/packet.zig"); ctx.addTestFile("src/packet.zig");
ctx.addTestFile("src/identity.zig");
} }

View file

@ -54,6 +54,7 @@ pub fn resolveEngine(comptime provider: PartialEngine) Engine {
.sha512 = provider.sha512 orelse SHA512.DefaultImplementation, .sha512 = provider.sha512 orelse SHA512.DefaultImplementation,
.x25519 = provider.x25519 orelse X25519.DefaultImplementation, .x25519 = provider.x25519 orelse X25519.DefaultImplementation,
}; };
} }

View file

@ -10,10 +10,6 @@ pub const CBC256_Implementation = struct {
// TODO // TODO
pub const CBC265_DefaultImplementation = struct { 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 { pub fn encrypt(key: *const [32]u8, iv: *const [16]u8, data: *const []u8) !void {
_ = key; _ = key;
_ = iv; _ = iv;

View file

@ -9,34 +9,21 @@ pub const Implementation = struct {
}; };
// TODO // TODO
pub fn defaultImplementation() type { pub const defaultImplementation = struct {
const Ed25519 = @import("std").crypto.sign.Ed25519; pub fn generateKeys(privkey_buffer: *[32]u8) !void {
_ = 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; _ = privkey_buffer;
return error.NotImplemented;
} }
pub fn sign(key: *const [32]u8, data: *const []const u8, signature_out: *const [64]u8) !void { pub fn sign(key: *const [32]u8, data: *const []const u8, signature_out: *const [64]u8) !void {
_ = key; _ = key;
_ = data; _ = data;
_ = signature_out; _ = signature_out;
return error.NotImplemented;
} }
pub fn verify(signature: *const [64]u8, data: *const []const u8) !void { pub fn verify(signature: *const [64]u8, data: *const []const u8) !void {
_ = signature; _ = signature;
_ = data; _ = data;
return error.NotImplemented;
} }
}; };
}

View file

@ -4,6 +4,4 @@ pub const Implementation = struct {
pub const defaultImplementation = struct { pub const defaultImplementation = struct {
const Hkdf = @import("std").crypto.kdf.hkdf.Hkdf;
}; };

View file

@ -4,12 +4,4 @@ pub const Implementation = struct {
pub const defaultImplementation = 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;
}
}; };

View file

@ -1,18 +1,7 @@
pub const Implementation = struct { pub const Implementation = struct {
hash: *const fn (buffer: []const u8, out: []u8) void,
}; };
pub const defaultImplementation = struct { 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, .{});
}
}; };

View file

@ -1,18 +1,7 @@
pub const Implementation = struct { pub const Implementation = struct {
hash: *const fn (buffer: []const u8, out: []u8) void,
}; };
pub const defaultImplementation = struct { 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, .{});
}
}; };

View file

@ -4,8 +4,4 @@ pub const Implementation = struct {
pub const defaultImplementation = 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
}; };

View file

@ -5,14 +5,13 @@
// //
pub const Type = enum(u2) { pub const Type = enum(u2) {
single = 0b0, single = 0x00,
group = 0b01, group = 0x01,
plain = 0b10, plain = 0x02,
link = 0b11, link = 0x03,
}; };
// From the reference implementation, seems weird pub const ProofStrategy = enum(u2) {
pub const ProofStrategy = enum(u8) {
prove_none = 0x21, prove_none = 0x21,
prove_app = 0x22, prove_app = 0x22,
prove_all = 0x23, prove_all = 0x23,
@ -29,33 +28,15 @@ pub const Direction = enum(u2) {
out = 0x12, out = 0x12,
}; };
///////////////// Enums ///////////////// Functions
// //
const Destination = struct { //////// Helper functions
//
name: []const u8,
aspects: [][]const u8,
direction: Direction,
type: Type,
//////// Public functions //////// Public functions
// //
// TODO
pub fn hash(self: *Destination, destination_buffer: [128]u8) !void {
_ = self;
_ = destination_buffer;
}
// TODO
pub fn announce() !void {}
};
///////////////// Helper functions
//
///////////////// Tests ///////////////// Tests
// //

View file

@ -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;

View file

@ -1,8 +1,13 @@
///////////////// Imports ///////////////// Module
// //
const CryptoEngine = @import("crypto.zig").Engine; const Self = @This();
const Destination = @import("destination.zig");
header: PacketHeader,
address1: [ADDRESS_SIZE]u8,
address2: [ADDRESS_SIZE]u8,
context: PacketContext,
data: []u8,
///////////////// Constants ///////////////// Constants
@ -32,6 +37,13 @@ pub const PropagationType = enum(u1) {
transport = 1 transport = 1
}; };
pub const DestinationType = enum(u2) {
single = 0b0,
group = 0b01,
plain = 0b10,
link = 0b11,
};
pub const PacketType = enum(u2) { pub const PacketType = enum(u2) {
data = 0b0, data = 0b0,
announce = 0b01, announce = 0b01,
@ -71,30 +83,40 @@ pub const PacketHeader = packed struct {
header: HeaderType, header: HeaderType,
context: ContextFlag, context: ContextFlag,
propagation: PropagationType, propagation: PropagationType,
destination: Destination.Type, destination: DestinationType,
packet: PacketType, packet: PacketType,
hops: u8, hops: u8,
}; };
///////////////// Functions
///////////////// Structs
// //
const Packet = struct { //////// Helper functions
const Self = @This();
///////////////// Fields
// //
header: PacketHeader, // Copies serialized data (as a byte array) into any structure type
address1: [ADDRESS_SIZE]u8, fn copyToPacket(dst: anytype, src: []const u8, offset: usize, count: usize) !usize {
address2: [ADDRESS_SIZE]u8, if (count == 0) return 0;
context: PacketContext, if (src.len < offset + count) return error.BufferTooShort;
data: []u8,
///////////////// Public functions const dst_ptr: []u8 = @ptrCast(dst);
if (dst_ptr.len != count) return error.MismatchedLengths;
@memcpy(dst_ptr, src[offset .. offset + count]);
return offset + count;
}
// Returns the size of the packet in bytes
fn getPacketSize(data_size: usize, has_two_addresses: bool) usize {
var res = @sizeOf(PacketHeader) + ADDRESS_SIZE + @sizeOf(PacketContext) + data_size;
if (has_two_addresses) res += ADDRESS_SIZE;
return res;
}
//////// Public functions
// //
pub fn serialize(packet: *const Self, output_buffer: []u8) !usize { pub fn serialize(packet: *const Self, output_buffer: []u8) !usize {
@ -146,38 +168,6 @@ const Packet = struct {
offset = try copyToPacket(packet.data, message_buffer, offset, message_buffer.len - offset); offset = try copyToPacket(packet.data, message_buffer, offset, message_buffer.len - offset);
} }
};
// pub fn Packet(comptime crypto_engine: CryptoEngine) type {
// return struct {};
// }
///////////////// Helper functions
//
// Copies serialized data (as a byte array) into any structure type
fn copyToPacket(dst: anytype, src: []const u8, offset: usize, count: usize) !usize {
if (count == 0) return 0;
if (src.len < offset + count) return error.BufferTooShort;
const dst_ptr: []u8 = @ptrCast(dst);
if (dst_ptr.len != count) return error.MismatchedLengths;
@memcpy(dst_ptr, src[offset .. offset + count]);
return offset + count;
}
// Returns the size of the packet in bytes
fn getPacketSize(data_size: usize, has_two_addresses: bool) usize {
var res = @sizeOf(PacketHeader) + ADDRESS_SIZE + @sizeOf(PacketContext) + data_size;
if (has_two_addresses) res += ADDRESS_SIZE;
return res;
}
///////////////// Tests ///////////////// Tests
// //
@ -191,8 +181,8 @@ const asBytes = std.mem.asBytes;
// //
// Serializes the given packet and makes sure the output is correct // Serializes the given packet and makes sure the output is correct
fn testPacketSerialization(packet: *const Packet) !void { fn testPacketSerialization(packet: *const Self) !void {
const buf_size = comptime @sizeOf(Packet) + MAX_DATA_SIZE; const buf_size = comptime @sizeOf(Self) + MAX_DATA_SIZE;
var buf: [buf_size]u8 = undefined; var buf: [buf_size]u8 = undefined;
const res: usize = try packet.serialize(&buf); const res: usize = try packet.serialize(&buf);
const has_second_address = packet.header.header == HeaderType.type2; 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; 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) return headersEql(&p1.header, &p2.header)
and memeql(u8, &p1.address1, &p2.address1) and memeql(u8, &p1.address1, &p2.address1)
and memeql(u8, &p1.address2, &p2.address2) and memeql(u8, &p1.address2, &p2.address2)
@ -252,7 +242,7 @@ test "Basic serialization: header type 1, max data size" {
.header = HeaderType.type1, .header = HeaderType.type1,
.context = ContextFlag.set, .context = ContextFlag.set,
.propagation = PropagationType.transport, .propagation = PropagationType.transport,
.destination = Destination.Type.single, .destination = DestinationType.single,
.packet = PacketType.announce, .packet = PacketType.announce,
.hops = 0, .hops = 0,
}; };
@ -260,7 +250,7 @@ test "Basic serialization: header type 1, max data size" {
const data_size = MAX_DATA_SIZE; const data_size = MAX_DATA_SIZE;
var data: [data_size]u8 = undefined; var data: [data_size]u8 = undefined;
const packet: Packet = .{ const packet: Self = .{
.header = header, .header = header,
.address1 = undefined, .address1 = undefined,
.address2 = undefined, .address2 = undefined,
@ -268,7 +258,7 @@ test "Basic serialization: header type 1, max data size" {
.data = &data, .data = &data,
}; };
try testPacketSerialization(&packet); try packet.testPacketSerialization();
} }
test "Basic serialization: header type 2, max data size" { 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, .header = HeaderType.type2,
.context = ContextFlag.set, .context = ContextFlag.set,
.propagation = PropagationType.transport, .propagation = PropagationType.transport,
.destination = Destination.Type.single, .destination = DestinationType.single,
.packet = PacketType.announce, .packet = PacketType.announce,
.hops = 0, .hops = 0,
}; };
@ -285,7 +275,7 @@ test "Basic serialization: header type 2, max data size" {
const data_size = MAX_DATA_SIZE; const data_size = MAX_DATA_SIZE;
var data: [data_size]u8 = undefined; var data: [data_size]u8 = undefined;
const packet: Packet = .{ const packet: Self = .{
.header = header, .header = header,
.address1 = undefined, .address1 = undefined,
.address2 = undefined, .address2 = undefined,
@ -293,7 +283,7 @@ test "Basic serialization: header type 2, max data size" {
.data = &data, .data = &data,
}; };
try testPacketSerialization(&packet); try packet.testPacketSerialization();
} }
test "Basic serialization: header type 1, medium data size" { 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, .header = HeaderType.type1,
.context = ContextFlag.set, .context = ContextFlag.set,
.propagation = PropagationType.transport, .propagation = PropagationType.transport,
.destination = Destination.Type.single, .destination = DestinationType.single,
.packet = PacketType.announce, .packet = PacketType.announce,
.hops = 0, .hops = 0,
}; };
@ -310,7 +300,7 @@ test "Basic serialization: header type 1, medium data size" {
const data_size = MAX_DATA_SIZE / 2 + 3; const data_size = MAX_DATA_SIZE / 2 + 3;
var data: [data_size]u8 = undefined; var data: [data_size]u8 = undefined;
const packet: Packet = .{ const packet: Self = .{
.header = header, .header = header,
.address1 = undefined, .address1 = undefined,
.address2 = undefined, .address2 = undefined,
@ -318,7 +308,7 @@ test "Basic serialization: header type 1, medium data size" {
.data = &data, .data = &data,
}; };
try testPacketSerialization(&packet); try packet.testPacketSerialization();
} }
test "Basic serialization: header type 2, medium data size" { 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, .header = HeaderType.type2,
.context = ContextFlag.set, .context = ContextFlag.set,
.propagation = PropagationType.transport, .propagation = PropagationType.transport,
.destination = Destination.Type.single, .destination = DestinationType.single,
.packet = PacketType.announce, .packet = PacketType.announce,
.hops = 0, .hops = 0,
}; };
@ -335,7 +325,7 @@ test "Basic serialization: header type 2, medium data size" {
const data_size = MAX_DATA_SIZE / 2 + 3; const data_size = MAX_DATA_SIZE / 2 + 3;
var data: [data_size]u8 = undefined; var data: [data_size]u8 = undefined;
const packet: Packet = .{ const packet: Self = .{
.header = header, .header = header,
.address1 = undefined, .address1 = undefined,
.address2 = undefined, .address2 = undefined,
@ -343,7 +333,7 @@ test "Basic serialization: header type 2, medium data size" {
.data = &data, .data = &data,
}; };
try testPacketSerialization(&packet); try packet.testPacketSerialization();
} }
test "Serialize / Deserialize Packet: Header type2, Medium data size" { 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, .header = HeaderType.type2,
.context = ContextFlag.set, .context = ContextFlag.set,
.propagation = PropagationType.transport, .propagation = PropagationType.transport,
.destination = Destination.Type.single, .destination = DestinationType.single,
.packet = PacketType.announce, .packet = PacketType.announce,
.hops = 0, .hops = 0,
}; };
@ -360,7 +350,7 @@ test "Serialize / Deserialize Packet: Header type2, Medium data size" {
const data_size = MAX_DATA_SIZE / 2 + 3; const data_size = MAX_DATA_SIZE / 2 + 3;
var data: [data_size]u8 = undefined; var data: [data_size]u8 = undefined;
const packet: Packet = .{ const packet: Self = .{
.header = header, .header = header,
.address1 = undefined, .address1 = undefined,
.address2 = 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; const buf_size = comptime @sizeOf(PacketHeader) + 2*ADDRESS_SIZE + @sizeOf(PacketContext) + data_size;
var buf: [buf_size]u8 = undefined; var buf: [buf_size]u8 = undefined;
var res_packet: Packet = undefined; var res_packet: Self = undefined;
var res_data: [data_size]u8 = undefined; var res_data: [data_size]u8 = undefined;
res_packet.data = &res_data; res_packet.data = &res_data;
_ = try packet.serialize(&buf); _ = try packet.serialize(&buf);

View file

@ -4,10 +4,10 @@ const crypto = @import("crypto.zig");
// You can pass your own cryptographic functions to take advantage of your // You can pass your own cryptographic functions to take advantage of your
// platform or use the library's software implementations for compatibility // platform or use the library's software implementations for compatibility
// Use its return value to access the library modules // Use its return value to access the library modules
pub fn RnsZero(comptime crypto_provider: crypto.PartialEngine) type { pub fn RnsZero(comptime cryptoProvider: crypto.PartialEngine) type {
const crypto_engine = crypto.resolveEngine(crypto_provider); const cryptoEngine = crypto.resolveEngine(cryptoProvider);
_ = cryptoEngine;
return struct { return struct {
pub const packet = @import("packet.zig"); pub const packet = @import("packet.zig");
pub const identity = @import("identity.zig").Identity(crypto_engine);
}; };
} }