Elasticity

Simple Hashing with AF_ALG

ddiss

What 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.

Tags: AF_ALGhashLinux.