2
votes

The Linux kernel added a user space API to its crypto functions at 2.6 via a new new socket family AF_ALG. Also see crypto: af_alg - User-space interface for Crypto API on LWN.

I'm working with Gentoo, and it requires one to configure and build the kernel. It appears the default settings omit AF_ALG, so I'm [currently] working with a kernel that lacks the support. OpenSSL 1.1.0 has an Engine interface into the crypto API. Its failing its self tests due to lack of support for AF_ALG.

I'd like to know how to detect availability of AF_ALG at both compile time and runtime. I have not found a way to detect availability at compile time. I think we can use alg_get_type to detect runtime availability, but I'm not certain.

How can I determine availability of AF_ALG at compile time and at runtime?


The socket(2) man pages has this to say: "Some socket types may not be implemented by all protocol families." But it does not discuss how to detect availability.

The kernel docs cover the API in Chapter 4. User Space Interface, but it does not appear to discuss how to detect availability.


For completeness, it looks like the following kernel configuration parameters need to be set for Gentoo (from Marek VaĊĦut's Utilizing the crypto accelerators):

  • CONFIG_CRYPTO_USER_API=m
  • CONFIG_CRYPTO_USER_API_HASH=m
  • CONFIG_CRYPTO_USER_API_SKCIPHER=m
2
On a side note, I wonder who decided it was sensible to make the main entry point to their new crypto API be an address family. - user253751
@immibis - I'm just guessing, but I think it had something to do with asynchronous I/O, syscall, __NR_io_setup, __NR_eventfd and __NR_io_destroy. - jww

2 Answers

1
votes

I think I can answer some of the second question, runtime availability, with the following:

int ret = socket(AF_ALG, SOCK_SEQPACKET, 0);
if (ret != -1)
  close(ret);

int supported = ret != -1;
1
votes

I'd say the only way to detect at compile time is to write a separate program that will do a runtime check for AF_ALG sockets and create a header file with a define such as #define AF_ALG_AVAILABLE.

Expanding on your answer to the second question, you may want to make sure errno holds EAFNOSUPPORT. Otherwise, another error, such as being out of file descriptors, will make your program falsely believe that AF_ALG is not supported, which could be bad if you are checking for AF_ALG at compile time using my method.

Checking at compile time:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/if_alg.h>

int main(){
    //Alternatively you can set the path to argv[1]
    FILE *f = fopen("/path/to/output/file", "w");
    if(f == NULL){
        //Handle error
    }
    int sockfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
    if(sockfd == -1){
        if(errno == EAFNOSUPPORT){
            //Unavailable, put whatever you want here
            fprintf(f, "#define AF_ALG_UNAVAILABLE\n");
        } else {
            //Unable to detect for some other error
        }
    } else { //AF_ALG is available
        fprintf(f, "#define AF_ALG_AVAILABLE\n");
    }
    close(sockfd);
    fclose(f);
    return 0;
}

Then just compile and run that in your makefile, and you will find your header file where you put it. Then you can simply select what code to use using #ifdef AF_ALG_AVAILABLE.