Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ This file records each release. The format follows [Keep a Changelog](https://ke

## Unreleased

### Added

- The `AF_ALG` sockets with the type `skcipher`, as crypto/algif_skcipher.c of Linux, for `ecb(aes)`, `cbc(aes)`, `ctr(aes)` and `xts(aes)` of `rk-crypto`. A `sendmsg` gives the operation with `ALG_SET_OP` and the IV with `ALG_SET_IV` in control messages, and adds the data to the queue. A `recv` encrypts or decrypts the data of the queue in blocks. With `MSG_MORE`, the operation continues in the next `send`, and the IV goes from one `recv` to the next. libcryptsetup uses these sockets to open a LUKS2 key slot without dm-crypt (#541).

## [0.5.24] - 2026-11-12

### Added
Expand Down
1 change: 1 addition & 0 deletions _typos.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ controllen = "controllen" # msg_controllen of struct msghdr
BA = "BA" # BARs, PCI base address registers, split by the checker
exportfs = "exportfs" # the NFS export code of Linux and the group of fstests
IIF = "IIF" # RTA_IIF of rtnetlink, the input interface of a route
ede = "ede" # des3_ede, the triple DES of Linux (encrypt, decrypt, encrypt)
OIF = "OIF" # RTA_OIF of rtnetlink, the output interface of a route
Parm = "Parm" # InParmProbs of /proc/net/snmp, the ICMP parameter problems
Ofo = "Ofo" # OfoPruned of /proc/net/netstat, the out of order queue of TCP
Expand Down
10 changes: 7 additions & 3 deletions net/rk-net/src/alg/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,9 @@ impl HashSocket {
return Ok(());
}
self.bound.check_key(|tfm| {
let Tfm::Hash(h) = tfm;
ctx.hash = h.box_clone();
if let Tfm::Hash(h) = tfm {
ctx.hash = h.box_clone();
}
})?;
ctx.nokey = false;
Ok(())
Expand Down Expand Up @@ -122,7 +123,10 @@ impl Socket for HashSocket {
self.check_key(&mut ctx)?;
ctx.more.then(|| ctx.hash.box_clone())
};
let Child::Hash(child) = self.bound.accept()?;
// The bound socket of a hash socket has a hash.
let Child::Hash(child) = self.bound.accept()? else {
return Err(Errno::EINVAL);
};
if let Some(hash) = state {
let mut c = child.ctx.lock();
c.hash = hash;
Expand Down
13 changes: 12 additions & 1 deletion net/rk-net/src/alg/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
//! `setsockopt` with the level `SOL_ALG` and `ALG_SET_KEY` sets the key. `accept` on the bound
//! socket gives an operation socket. The program writes the data to the operation socket and
//! reads the result from it. The module `hash` has the operation sockets of the type `hash`, as
//! crypto/algif_hash.c of Linux.
//! crypto/algif_hash.c of Linux, and the module `skcipher` has the operation sockets of the type
//! `skcipher`, as crypto/algif_skcipher.c of Linux.
//!
//! The algorithms come from the crate `rk_crypto`. A program can bind only the algorithms of the
//! allow list of the type, as `af_alg_check_restriction` of Linux with `crypto.af_alg_restrict`
Expand All @@ -17,6 +18,7 @@
//! key of the bound socket cannot change while it has an operation socket with a key.

mod hash;
mod skcipher;
#[cfg(test)]
mod tests;

Expand Down Expand Up @@ -84,26 +86,30 @@ fn check_restriction(name: &str, list: AllowList) -> Result<()> {
/// The algorithm of a bound socket, as the `private` of a `struct alg_sock` of Linux.
enum Tfm {
Hash(Box<dyn rk_crypto::Hash>),
Skcipher(Box<dyn rk_crypto::Skcipher>),
}

impl Tfm {
/// Finds the algorithm `name` of the type `kind`, as the `bind` of a `struct af_alg_type`.
fn bind(kind: &str, name: &str) -> Result<Self> {
match kind {
"hash" => hash::bind(name).map(Self::Hash),
"skcipher" => skcipher::bind(name).map(Self::Skcipher),
_ => Err(Errno::ENOENT),
}
}

fn needs_key(&self) -> bool {
match self {
Self::Hash(h) => h.needs_key(),
Self::Skcipher(c) => c.needs_key(),
}
}

fn set_key(&mut self, key: &[u8]) -> Result<()> {
match self {
Self::Hash(h) => h.set_key(key),
Self::Skcipher(c) => c.set_key(key),
}
}
}
Expand All @@ -123,12 +129,14 @@ struct Bound(SpinLock<Shared>);
/// A new operation socket.
enum Child {
Hash(Arc<hash::HashSocket>),
Skcipher(Arc<skcipher::SkcipherSocket>),
}

impl Child {
fn socket(self) -> Arc<dyn Socket> {
match self {
Self::Hash(s) => s,
Self::Skcipher(s) => s,
}
}
}
Expand All @@ -144,6 +152,9 @@ impl Bound {
let nokey = tfm.needs_key();
let child = match tfm {
Tfm::Hash(h) => Child::Hash(hash::HashSocket::new(self.clone(), h.box_clone(), nokey)),
Tfm::Skcipher(c) => {
Child::Skcipher(skcipher::SkcipherSocket::new(self.clone(), c.box_clone(), nokey))
}
};
s.children += 1;
if nokey {
Expand Down
Loading
Loading