Compare commits

..

31 Commits

Author SHA1 Message Date
6b60e04513 don't seal sync_mem 2025-10-27 10:15:55 +01:00
b72ea11712 get shared_memory_heap from git repository 2025-10-23 18:20:47 +02:00
ebb738445b Make number of spawned ed25519 agent configurable through environment variables 2025-05-14 11:27:58 +02:00
0f16f071b4 Revert last three commits
This reverts commit a97adf188b.
This reverts commit c61fb504c6
This reverts commit 0bb5c528ee
2025-05-14 11:23:23 +02:00
0bb5c528ee use memfd_secret for sync memory 2025-04-07 12:06:59 +02:00
c61fb504c6 remove seal from shared memory page 2025-04-04 13:10:45 +02:00
a97adf188b change synchronization with agent 2025-04-04 12:18:07 +02:00
2b23baa3af remove lazy_cell feature 2025-03-04 10:36:32 +01:00
68ff86b8c6 sync changes from artifact 2025-02-25 17:26:25 +01:00
d770fd2641 borrow inputs to ed25519 sign 2024-10-14 17:01:05 +02:00
5c05bd7921 fix: use correct size for ed25519 signature 2024-10-11 14:55:54 +02:00
57dae7f181 feat: re-export SharedPtr 2024-10-10 17:46:20 +02:00
14f782b46a feat: add Ed25519 2024-10-10 17:44:15 +02:00
5c4067608c fix: set correct size for MLKEM ciphertext 2024-10-10 16:47:13 +02:00
cbf0454517 chore: update to latest shared_memory_heap 2024-10-10 16:44:56 +02:00
d36eb9afcf fix: use proper ipc id for decapsulate call 2024-08-28 09:07:37 +02:00
05eb75d932 feat: add mlkem decap 2024-08-27 17:36:53 +02:00
3922222898 feat: add mlkem encap 2024-08-27 16:53:10 +02:00
46c9a6e499 feat: seperate keyfiles per agent 2024-08-27 16:06:34 +02:00
31126ad5eb feat: add mlkem keygen 2024-08-27 15:35:14 +02:00
312007ea7f chore: update agent 2024-08-23 11:02:10 +02:00
2ed3949ee1 fix: null terminate path of agent 2024-05-08 16:59:50 +02:00
54565cb769 chore: update shared_memory_heap 2024-05-07 10:45:41 +02:00
4857476043 feat: get rid of lifetime annotations 2024-05-07 10:38:28 +02:00
bd7d80765c feat: add Deref trait to X25519 types 2024-05-06 17:19:59 +02:00
6ec9735709 feat: pass keyfile to agent 2024-05-06 16:14:50 +02:00
bbdecfc8cb feat: add new ipc call 2024-05-06 15:55:12 +02:00
26a09b5ec2 feat: add trait to convert slice into X25519PrivKey 2024-05-06 14:19:15 +02:00
bd19c3639a feat: add trait to convert slice into X25519PublicKey 2024-05-06 10:44:04 +02:00
0edc34a236 chore: update shared_memory_heap 2024-04-29 15:50:44 +02:00
82d0f7a3f5 chore: update shared_memory_heap 2024-04-29 15:32:02 +02:00
6 changed files with 372 additions and 62 deletions

12
Cargo.lock generated
View File

@@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
version = 4
[[package]]
name = "agent_lib"
@@ -13,20 +13,20 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.82"
version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6"
[[package]]
name = "libc"
version = "0.2.153"
version = "0.2.159"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
[[package]]
name = "shared_memory_heap"
version = "0.1.0"
source = "git+https://gitea.rixxc.de/rixxc/shared_memory_heap.git#5cd37dfc93aa9bc44df47571396dff70d773fcb2"
source = "git+https://gitea.rixxc.de/rixxc/shared_memory_heap.git#ef9bcc94fb04d7191514a249c78d608d2f7cb9a6"
dependencies = [
"libc",
]

View File

@@ -1,7 +1,8 @@
use anyhow::{bail, Result};
use libc::{
c_char, c_void, execve, fork, ftruncate, memfd_create, mmap, perror, syscall, SYS_futex,
FUTEX_WAIT, FUTEX_WAKE, MAP_FAILED, MAP_SHARED, PROT_READ, PROT_WRITE,
c_char, c_void, close, execve, fcntl, fork, ftruncate, memfd_create, mmap, perror, syscall,
SYS_futex, FUTEX_WAIT, FUTEX_WAKE, F_ADD_SEALS, F_SEAL_FUTURE_WRITE, MAP_FAILED, MAP_SHARED,
MFD_ALLOW_SEALING, PROT_READ, PROT_WRITE,
};
use shared_memory_heap::get_shared_mem_fd;
use std::{ffi::CString, path::Path, ptr, usize};
@@ -13,7 +14,7 @@ pub struct Agent {
unsafe impl Send for Agent {}
impl Agent {
pub(crate) unsafe fn new(path: &Path) -> Result<Self> {
pub(crate) unsafe fn new(agent_path: &Path, keyfile_path: &Path) -> Result<Self> {
let data_fd = get_shared_mem_fd();
let sync_fd = memfd_create("sync\x00".as_ptr() as *const c_char, 0);
@@ -46,15 +47,22 @@ impl Agent {
if child == 0 {
// child
close(0);
close(1);
close(2);
let path = CString::new(agent_path.as_os_str().as_encoded_bytes()).unwrap();
let data_fd = CString::new(data_fd.to_string()).unwrap();
let sync_fd = CString::new(sync_fd.to_string()).unwrap();
let args = [data_fd.as_ptr(), sync_fd.as_ptr(), ptr::null()];
execve(
path.as_os_str().as_encoded_bytes().as_ptr() as *const c_char,
args.as_ptr(),
let keyfile = CString::new(keyfile_path.as_os_str().as_encoded_bytes()).unwrap();
let args = [
data_fd.as_ptr(),
sync_fd.as_ptr(),
keyfile.as_ptr(),
ptr::null(),
);
];
execve(path.as_ptr() as *const c_char, args.as_ptr(), ptr::null());
perror("execve:\x00".as_ptr() as *const c_char);

128
src/ed25519.rs Normal file
View File

@@ -0,0 +1,128 @@
pub use shared_memory_heap::sharedptr::SharedPtr;
use crate::agent::Agent;
use std::{
ops::Deref,
path::Path,
sync::{LazyLock, Mutex},
};
static ED25519AGENT: LazyLock<Vec<Mutex<Agent>>> = LazyLock::new(|| {
let agent_path = std::env::var("ED25519_AGENT_PATH")
.expect("ED25519_AGENT_PATH environment variable missing");
let keyfile_path =
std::env::var("ED25519_KEYFILE").expect("Ed25519_KEYFILE environment variable missing");
let num_agents: usize = std::env::var("NUM_AGENTS")
.expect("NUM_AGENTS environment variable missing")
.parse()
.expect("NUM_AGENTS should be an integer");
let mut agents = Vec::with_capacity(num_agents);
for _ in 0..num_agents {
let agent = unsafe {
Agent::new(Path::new(&agent_path), Path::new(&keyfile_path))
.expect("Agent failed to start")
};
agents.push(Mutex::new(agent));
}
agents
});
#[derive(Debug)]
pub struct Ed25519PrivKey(SharedPtr);
#[derive(Debug)]
pub struct Ed25519PubKey(SharedPtr);
#[derive(Debug)]
pub struct Ed25519Signature(SharedPtr);
impl From<&[u8; 32]> for Ed25519PubKey {
fn from(value: &[u8; 32]) -> Self {
let mut pk = SharedPtr::new(32).unwrap();
pk.copy_from_slice(value);
Ed25519PubKey(pk)
}
}
impl From<&[u8; 8]> for Ed25519PrivKey {
fn from(value: &[u8; 8]) -> Self {
let mut sk = SharedPtr::new(8).unwrap();
sk.copy_from_slice(value);
Ed25519PrivKey(sk)
}
}
impl Deref for Ed25519PrivKey {
type Target = [u8; 8];
fn deref(&self) -> &Self::Target {
self.0.deref().try_into().expect("this should never fail")
}
}
impl Deref for Ed25519PubKey {
type Target = [u8; 32];
fn deref(&self) -> &Self::Target {
self.0.deref().try_into().expect("this should never fail")
}
}
impl Deref for Ed25519Signature {
type Target = [u8; 64];
fn deref(&self) -> &Self::Target {
self.0.deref().try_into().expect("this should never fail")
}
}
pub fn ed25519_keygen() -> (Ed25519PrivKey, Ed25519PubKey) {
let sk = Ed25519PrivKey(SharedPtr::new(8).unwrap());
let pk = Ed25519PubKey(SharedPtr::new(32).unwrap());
let mut agent = None;
while agent.is_none() {
agent = ED25519AGENT
.iter()
.map(|agent| agent.try_lock())
.filter(|agent| agent.is_ok())
.next();
}
let mut agent = agent.unwrap().unwrap();
unsafe {
agent.perform_ipc_call(0, &[sk.0.get_offset(), pk.0.get_offset()]);
}
drop(agent);
(sk, pk)
}
pub fn ed25519_sign(sk: &Ed25519PrivKey, msg: &SharedPtr) -> Ed25519Signature {
let sig = Ed25519Signature(SharedPtr::new(64).unwrap());
let mut agent = None;
while agent.is_none() {
agent = ED25519AGENT
.iter()
.map(|agent| agent.try_lock())
.filter(|agent| agent.is_ok())
.next();
}
let mut agent = agent.unwrap().unwrap();
unsafe {
agent.perform_ipc_call(
1,
&[
sk.0.get_offset(),
msg.get_offset(),
msg.get_size(),
sig.0.get_offset(),
],
);
}
drop(agent);
sig
}

View File

@@ -1,49 +1,6 @@
#![feature(lazy_cell)]
mod agent;
pub use shared_memory_heap::sharedptr::SharedPtr;
use agent::Agent;
use std::{
path::Path,
sync::{LazyLock, Mutex},
};
static AGENT: LazyLock<Mutex<Agent>> = LazyLock::new(|| {
let agent_path = std::env::var("AGENT_PATH").expect("AGENT_PATH environment variable missing");
let agent = unsafe { Agent::new(Path::new(&agent_path)).expect("Agent failed to start") };
Mutex::new(agent)
});
#[derive(Debug)]
pub struct X25519PrivKey<'a>(SharedPtr<'a, 8>);
#[derive(Debug)]
pub struct X25519PubKey<'a>(SharedPtr<'a, 32>);
#[derive(Debug)]
pub struct X25519SharedKey<'a>(SharedPtr<'a, 32>);
pub fn x25519_keygen<'a>() -> (X25519PrivKey<'a>, X25519PubKey<'a>) {
let sk = X25519PrivKey(SharedPtr::<8>::new().unwrap());
let pk = X25519PubKey(SharedPtr::<32>::new().unwrap());
let mut agent = AGENT.lock().unwrap();
unsafe {
agent.perform_ipc_call(0, &[sk.0.get_offset(), pk.0.get_offset()]);
}
(sk, pk)
}
pub fn x25519<'a>(sk: &X25519PrivKey, pk: &X25519PubKey) -> X25519SharedKey<'a> {
let out = X25519SharedKey(SharedPtr::<32>::new().unwrap());
let mut agent = AGENT.lock().unwrap();
unsafe {
agent.perform_ipc_call(1, &[out.0.get_offset(), sk.0.get_offset(), pk.0.get_offset()]);
}
out
}
mod agent;
pub mod ed25519;
pub mod mlkem;
pub mod x25519;

114
src/mlkem.rs Normal file
View File

@@ -0,0 +1,114 @@
pub use shared_memory_heap::sharedptr::SharedPtr;
use crate::agent::Agent;
use std::{
ops::Deref, path::Path, sync::{LazyLock, Mutex}
};
static MLKEMAGENT: LazyLock<Mutex<Agent>> = LazyLock::new(|| {
let agent_path = std::env::var("MLKEM_AGENT_PATH").expect("MLKEM_AGENT_PATH environment variable missing");
let keyfile_path = std::env::var("MLKEM_KEYFILE").expect("MLKEM_KEYFILE environment variable missing");
let agent = unsafe { Agent::new(Path::new(&agent_path), Path::new(&keyfile_path)).expect("Agent failed to start") };
Mutex::new(agent)
});
#[derive(Debug)]
pub struct MLKEMPrivKey(SharedPtr);
#[derive(Debug)]
pub struct MLKEMPubKey(SharedPtr);
#[derive(Debug)]
pub struct MLKEMCiphertext(SharedPtr);
#[derive(Debug)]
pub struct MLKEMSharedKey(SharedPtr);
impl From<&[u8; 1184]> for MLKEMPubKey {
fn from(value: &[u8; 1184]) -> Self {
let mut pk = SharedPtr::new(1184).unwrap();
pk.copy_from_slice(value);
MLKEMPubKey(pk)
}
}
impl From<&[u8; 8]> for MLKEMPrivKey {
fn from(value: &[u8; 8]) -> Self {
let mut sk = SharedPtr::new(8).unwrap();
sk.copy_from_slice(value);
MLKEMPrivKey(sk)
}
}
impl Deref for MLKEMPrivKey {
type Target = [u8; 8];
fn deref(&self) -> &Self::Target {
self.0.deref().try_into().expect("this should never fail")
}
}
impl Deref for MLKEMPubKey {
type Target = [u8; 1184];
fn deref(&self) -> &Self::Target {
self.0.deref().try_into().expect("this should never fail")
}
}
impl Deref for MLKEMCiphertext {
type Target = [u8; 1088];
fn deref(&self) -> &Self::Target {
self.0.deref().try_into().expect("this should never fail")
}
}
impl Deref for MLKEMSharedKey {
type Target = [u8; 32];
fn deref(&self) -> &Self::Target {
self.0.deref().try_into().expect("this should never fail")
}
}
pub fn mlkem_keygen() -> (MLKEMPrivKey, MLKEMPubKey) {
let sk = MLKEMPrivKey(SharedPtr::new(8).unwrap());
let pk = MLKEMPubKey(SharedPtr::new(1184).unwrap());
let mut agent = MLKEMAGENT.lock().unwrap();
unsafe {
agent.perform_ipc_call(0, &[sk.0.get_offset(), pk.0.get_offset()]);
}
drop(agent);
(sk, pk)
}
pub fn mlkem_encap(pk: &MLKEMPubKey) -> (MLKEMCiphertext, MLKEMSharedKey) {
let ct = MLKEMCiphertext(SharedPtr::new(1088).unwrap());
let ss = MLKEMSharedKey(SharedPtr::new(32).unwrap());
let mut agent = MLKEMAGENT.lock().unwrap();
unsafe {
agent.perform_ipc_call(1, &[ct.0.get_offset(), ss.0.get_offset(), pk.0.get_offset()]);
}
drop(agent);
(ct, ss)
}
pub fn mlkem_decap(ct: &MLKEMCiphertext, sk: &MLKEMPrivKey) -> MLKEMSharedKey {
let ss = MLKEMSharedKey(SharedPtr::new(32).unwrap());
let mut agent = MLKEMAGENT.lock().unwrap();
unsafe {
agent.perform_ipc_call(2, &[ss.0.get_offset(), ct.0.get_offset(), sk.0.get_offset()]);
}
drop(agent);
ss
}

103
src/x25519.rs Normal file
View File

@@ -0,0 +1,103 @@
pub use shared_memory_heap::sharedptr::SharedPtr;
use crate::agent::Agent;
use std::{
ops::Deref, path::Path, sync::{LazyLock, Mutex}
};
static X25519AGENT: LazyLock<Mutex<Agent>> = LazyLock::new(|| {
let agent_path = std::env::var("X25519_AGENT_PATH").expect("X25519_AGENT_PATH environment variable missing");
let keyfile_path = std::env::var("X25519_KEYFILE").expect("X25519_KEYFILE environment variable missing");
let agent = unsafe { Agent::new(Path::new(&agent_path), Path::new(&keyfile_path)).expect("Agent failed to start") };
Mutex::new(agent)
});
#[derive(Debug)]
pub struct X25519PrivKey(SharedPtr);
#[derive(Debug)]
pub struct X25519PubKey(SharedPtr);
#[derive(Debug)]
pub struct X25519SharedKey(SharedPtr);
impl From<&[u8; 32]> for X25519PubKey {
fn from(value: &[u8; 32]) -> Self {
let mut pk = SharedPtr::new(32).unwrap();
pk.copy_from_slice(value);
X25519PubKey(pk)
}
}
impl From<&[u8; 8]> for X25519PrivKey {
fn from(value: &[u8; 8]) -> Self {
let mut sk = SharedPtr::new(8).unwrap();
sk.copy_from_slice(value);
X25519PrivKey(sk)
}
}
impl Deref for X25519PrivKey {
type Target = [u8; 8];
fn deref(&self) -> &Self::Target {
self.0.deref().try_into().expect("this should never fail")
}
}
impl Deref for X25519PubKey {
type Target = [u8; 32];
fn deref(&self) -> &Self::Target {
self.0.deref().try_into().expect("this should never fail")
}
}
impl Deref for X25519SharedKey {
type Target = [u8; 32];
fn deref(&self) -> &Self::Target {
self.0.deref().try_into().expect("this should never fail")
}
}
pub fn x25519_keygen() -> (X25519PrivKey, X25519PubKey) {
let sk = X25519PrivKey(SharedPtr::new(8).unwrap());
let pk = X25519PubKey(SharedPtr::new(32).unwrap());
let mut agent = X25519AGENT.lock().unwrap();
unsafe {
agent.perform_ipc_call(0, &[sk.0.get_offset(), pk.0.get_offset()]);
}
drop(agent);
(sk, pk)
}
pub fn x22519_pubkey(sk: &X25519PrivKey) -> X25519PubKey {
let pk = X25519PubKey(SharedPtr::new(32).unwrap());
let mut agent = X25519AGENT.lock().unwrap();
unsafe {
agent.perform_ipc_call(1, &[sk.0.get_offset(), pk.0.get_offset()]);
}
drop(agent);
pk
}
pub fn x25519(sk: &X25519PrivKey, pk: &X25519PubKey) -> X25519SharedKey {
let out = X25519SharedKey(SharedPtr::new(32).unwrap());
let mut agent = X25519AGENT.lock().unwrap();
unsafe {
agent.perform_ipc_call(2, &[out.0.get_offset(), sk.0.get_offset(), pk.0.get_offset()]);
}
drop(agent);
out
}