From ed4a77766a0bd47a98eaf655d78d005370a5e7ea Mon Sep 17 00:00:00 2001 From: Aaron Kaiser Date: Thu, 10 Oct 2024 16:27:39 +0200 Subject: [PATCH] initial commit --- .envrc | 1 + .gitignore | 4 ++ Makefile | 25 ++++++++++ default.nix | 47 ++++++++++++++++++ src/agent.jazz | 128 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 205 insertions(+) create mode 100644 .envrc create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 default.nix create mode 100644 src/agent.jazz diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..1d953f4 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use nix diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d19d9ba --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +build +result +*.o +.direnv diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..12a6572 --- /dev/null +++ b/Makefile @@ -0,0 +1,25 @@ +JC ?= jasminc +CC ?= gcc +MAKE ?= make + +JASMIN_ARGS = -protect-calls -return-address-kind=mmx + +.PHONY: clean run + +all: build + @true + +build: build/agent.o + ar -crs build/libagent.a build/agent.o + +build/%.o: build/%.S + $(CC) $< -c -o $@ + +clean: + rm build/* 2> /dev/null || true + $(MAKE) -C syscall clean + +build/%.S: src/%.jazz + $(JC) $(JASMIN_ARGS) $< -o $@ + # remove the remaining ret calls to make sure that we don't execute any return. Those returns should not be called anyways due to the infinit loop + sed -i 's/ret/hlt/g' $@ diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..d89aaa4 --- /dev/null +++ b/default.nix @@ -0,0 +1,47 @@ +{ pkgs ? import { } }: +with pkgs; +let + jasmin-src = fetchFromGitHub { + owner = "jasmin-lang"; + repo = "jasmin"; + rev = "c2adabafb8df0a60e7cf4e56041d3be3aca387a3"; + hash = "sha256-ySw4eVbuV7suO8EjyaMOTqeNsPq1D6vsorCZlXffTPU="; + }; + + jasmin-drv = callPackage "${jasmin-src}/default.nix" { inherit pkgs; }; + jasmin = jasmin-drv.overrideAttrs { + name = "jasmin with syscalls"; + buildPhase = '' + make -C compiler/ CIL + make -C compiler/ + ''; + }; + + libjade = fetchFromGitHub { + owner = "Rixxc"; + repo = "libjade"; + rev = "612b7744f8942e4cc7a1ce6c9dfe3ab46e96d515"; + hash = "sha256-w7AgyGlcwlMyo94KFit3fTpyG7hlNsQQWElGFDEQRCQ="; + }; +in +stdenv.mkDerivation { + name = "ed25519-agent"; + src = nix-gitignore.gitignoreSource [ ] ./.; + + nativeBuildInputs = [ + gnumake + gcc + jasmin + ]; + + configurePhase = '' + mkdir build + ''; + + installPhase = '' + mkdir -p $out/lib + cp build/libagent.a $out/lib + ''; + + JASMINPATH = "Jade=${libjade}/src/"; +} diff --git a/src/agent.jazz b/src/agent.jazz new file mode 100644 index 0000000..c942048 --- /dev/null +++ b/src/agent.jazz @@ -0,0 +1,128 @@ +from Jade require "crypto_sign/ed25519/amd64/amd64-64-24k/ed25519.jinc" + +param int SK_SIZE = 32; +param int SHARED_MEM_SIZE = 1024; +param int PRIVATE_MEM_SIZE = 3200; + +inline fn extract_nth_ptr(reg u64 sync_mem shared_mem, inline int i) -> reg u64 { + reg u64 p; + + p = (u64)[sync_mem + (16 + i * 8)]; + p += shared_mem; + + return p; +} + +inline fn extract_ipc_id(reg u64 sync_mem) -> reg u64 { + reg u64 id; + + id = (u64)[sync_mem + 8]; + + return id; +} + +inline fn generate_keypair(reg u64 shared_mem sync_mem private_mem, stack u64 key_id) -> (stack u64, reg u64) { + reg u64 skptr idptr pkptr return_value; + + skptr = key_id * SK_SIZE; + skptr += private_mem; + + pkptr = extract_nth_ptr(sync_mem, shared_mem, 1); + + () = #spill(shared_mem, sync_mem); + + jade_ed25519_amd64_keygen(skptr, pkptr); + + () = #unspill(shared_mem, sync_mem); + + idptr = extract_nth_ptr(sync_mem, shared_mem, 0); + (u64)[idptr] = key_id; + + key_id += 1; + + return_value = 1; + return key_id, return_value; +} + +inline fn sign(reg u64 shared_mem sync_mem private_mem) -> reg u64 { + reg u64 skptr mptr len sigptr return_value; + + skptr = extract_nth_ptr(sync_mem, shared_mem, 0); + skptr = (u64)[skptr]; + skptr *= SK_SIZE; + skptr += private_mem; + + mptr = extract_nth_ptr(sync_mem, shared_mem, 1); + + len = extract_nth_ptr(sync_mem, shared_mem, 2); + len = (u64)[len]; + + sigptr = extract_nth_ptr(sync_mem, shared_mem, 3); + + jade_ed25519_amd64_sign(skptr, mptr, len, sigptr); + + return_value = 1; + return return_value; +} + +export fn agent_start(#public reg u64 shared_mem sync_mem, #private reg u64 private_mem_fd) { + stack u64 key_id return_value; + reg u64 private_mem; + // Futex varibles + reg u64 futex_op val timeout uaddr2 val3 woken_up; + // Mmap variables + reg u64 addr len prot flag off; + + () = #spill(shared_mem, sync_mem); + + private_mem_fd = private_mem_fd; + addr = 0; + len = PRIVATE_MEM_SIZE; + prot = 3; // PROT_READ | PROT_WRITE + flag = 1; // MAP_SHARED; + off = 0; + private_mem = #mmap(addr, len, prot, flag, private_mem_fd, off); + + () = #spill(private_mem); + + key_id = 0; + + while (true) { + while { + () = #unspill(sync_mem); + futex_op = 0; + val = 0; + timeout = 0; + uaddr2 = 0; + val3 = 0; + woken_up = #futex(sync_mem, futex_op, val, timeout, uaddr2, val3); + } (woken_up != 0) + + () = #unspill(shared_mem, sync_mem, private_mem); + + reg u64 id; + id = extract_ipc_id(sync_mem); + + if (id == 0) { + key_id, return_value = generate_keypair(shared_mem, sync_mem, private_mem, key_id); + } else { + if (id == 1) { + return_value = sign(shared_mem, sync_mem, private_mem); + } + } + + () = #unspill(sync_mem); + + (u64)[sync_mem + 16] = return_value; + + while { + () = #unspill(sync_mem); + futex_op = 1; + val = 1; + timeout = 0; + uaddr2 = 0; + val3 = 0; + woken_up = #futex(sync_mem, futex_op, val, timeout, uaddr2, val3); + } (woken_up != 1) + } +}