Wednesday, June 18, 2025

Simple Hashing with AF_ALG

My previous post demonstrated how the Linux kernel's AF_ALG socket type can be used with io_uring for fast hashing.

I wasn't very happy with the complexity of the io_uring based implementation, so set out to write something much simpler with plain syscalls. 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.

No comments:

Post a Comment

Comments are moderated due to spammer abuse.