Simple Hashing with AF_ALG
ddissWhat came out was just over 100 lines of boring, uncomplicated C. Better still, use of splice() for copy-offload sees it perform very similar to the io_uring based implementation on my systems.
I've published the BSD-3-Clause licensed source at https://github.com/ddiss/splice-digest, with the main snippets below:
#define SPLICE_MAX (1024 * 1024)
...
int main(int argc, char *argv[])
{
...
struct sockaddr_alg sa = {
.salg_family = AF_ALG,
.salg_type = "hash",
};
...
infd = open(infile, O_RDONLY);
...
sfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
...
memcpy(sa.salg_name, alg, alg_len + 1);
if (bind(sfd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
...
}
outfd = accept(sfd, NULL, 0);
...
if (pipe(pipefds) < 0)
err(-1, "pipe");
...
for (insize = st.st_size; insize; insize -= got) {
size_t tryl = (insize < SPLICE_MAX ? insize : SPLICE_MAX);
l = splice(infd, NULL, pipefds[1], NULL, tryl, 0);
...
got = splice(pipefds[0], NULL, outfd, NULL, l, SPLICE_F_MORE);
...
}
fprintf(stdout, "Spliced %s(%s): ", alg, infile);
print_hash_result(outfd);
putc('\n', stdout);
}
Hopefully this convinces a few people to drop those external crypto libraries in favour of Linux AF_ALG.
Update 2026-05-01: The recent copy.fail (CVE-2026-31431) bug is alarming, but this article hopefully serves as a reminder that there are legitimate use cases for AF_ALG.