Home | History | Annotate | Line # | Download | only in engines
      1      1.1  christos /*
      2      1.1  christos  * Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved.
      3      1.1  christos  *
      4      1.1  christos  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5      1.1  christos  * this file except in compliance with the License.  You can obtain a copy
      6      1.1  christos  * in the file LICENSE in the source distribution or at
      7      1.1  christos  * https://www.openssl.org/source/license.html
      8      1.1  christos  */
      9      1.1  christos 
     10      1.1  christos /* We need to use some deprecated APIs */
     11      1.1  christos #define OPENSSL_SUPPRESS_DEPRECATED
     12      1.1  christos 
     13      1.1  christos /* Required for vmsplice */
     14      1.1  christos #ifndef _GNU_SOURCE
     15  1.1.1.2  christos #define _GNU_SOURCE
     16      1.1  christos #endif
     17      1.1  christos #include <stdio.h>
     18      1.1  christos #include <string.h>
     19      1.1  christos #include <unistd.h>
     20      1.1  christos 
     21      1.1  christos #include <openssl/engine.h>
     22      1.1  christos #include <openssl/async.h>
     23      1.1  christos #include <openssl/err.h>
     24      1.1  christos #include "internal/nelem.h"
     25      1.1  christos 
     26      1.1  christos #include <sys/socket.h>
     27      1.1  christos #include <linux/version.h>
     28  1.1.1.2  christos #define K_MAJ 4
     29  1.1.1.2  christos #define K_MIN1 1
     30  1.1.1.2  christos #define K_MIN2 0
     31  1.1.1.2  christos #if LINUX_VERSION_CODE < KERNEL_VERSION(K_MAJ, K_MIN1, K_MIN2) || !defined(AF_ALG)
     32  1.1.1.2  christos #ifndef PEDANTIC
     33  1.1.1.2  christos #warning "AFALG ENGINE requires Kernel Headers >= 4.1.0"
     34  1.1.1.2  christos #warning "Skipping Compilation of AFALG engine"
     35  1.1.1.2  christos #endif
     36      1.1  christos void engine_load_afalg_int(void);
     37      1.1  christos void engine_load_afalg_int(void)
     38      1.1  christos {
     39      1.1  christos }
     40      1.1  christos #else
     41      1.1  christos 
     42  1.1.1.2  christos #include <linux/if_alg.h>
     43  1.1.1.2  christos #include <fcntl.h>
     44  1.1.1.2  christos #include <sys/utsname.h>
     45  1.1.1.2  christos 
     46  1.1.1.2  christos #include <linux/aio_abi.h>
     47  1.1.1.2  christos #include <sys/syscall.h>
     48  1.1.1.2  christos #include <errno.h>
     49      1.1  christos 
     50  1.1.1.2  christos /* clang-format off */
     51      1.1  christos # include "e_afalg.h"
     52      1.1  christos # include "e_afalg_err.c"
     53  1.1.1.2  christos /* clang-format on */
     54  1.1.1.2  christos 
     55  1.1.1.2  christos #ifndef SOL_ALG
     56  1.1.1.2  christos #define SOL_ALG 279
     57  1.1.1.2  christos #endif
     58  1.1.1.2  christos 
     59  1.1.1.2  christos #ifdef ALG_ZERO_COPY
     60  1.1.1.2  christos #ifndef SPLICE_F_GIFT
     61  1.1.1.2  christos #define SPLICE_F_GIFT (0x08)
     62  1.1.1.2  christos #endif
     63  1.1.1.2  christos #endif
     64      1.1  christos 
     65  1.1.1.2  christos #define ALG_AES_IV_LEN 16
     66  1.1.1.2  christos #define ALG_IV_LEN(len) (sizeof(struct af_alg_iv) + (len))
     67  1.1.1.2  christos #define ALG_OP_TYPE unsigned int
     68  1.1.1.2  christos #define ALG_OP_LEN (sizeof(ALG_OP_TYPE))
     69      1.1  christos 
     70  1.1.1.2  christos #ifdef OPENSSL_NO_DYNAMIC_ENGINE
     71      1.1  christos void engine_load_afalg_int(void);
     72  1.1.1.2  christos #endif
     73      1.1  christos 
     74      1.1  christos /* Local Linkage Functions */
     75      1.1  christos static int afalg_init_aio(afalg_aio *aio);
     76      1.1  christos static int afalg_fin_cipher_aio(afalg_aio *ptr, int sfd,
     77  1.1.1.2  christos     unsigned char *buf, size_t len);
     78      1.1  christos static int afalg_create_sk(afalg_ctx *actx, const char *ciphertype,
     79  1.1.1.2  christos     const char *ciphername);
     80      1.1  christos static int afalg_destroy(ENGINE *e);
     81      1.1  christos static int afalg_init(ENGINE *e);
     82      1.1  christos static int afalg_finish(ENGINE *e);
     83      1.1  christos static const EVP_CIPHER *afalg_aes_cbc(int nid);
     84      1.1  christos static cbc_handles *get_cipher_handle(int nid);
     85      1.1  christos static int afalg_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
     86  1.1.1.2  christos     const int **nids, int nid);
     87      1.1  christos static int afalg_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
     88  1.1.1.2  christos     const unsigned char *iv, int enc);
     89      1.1  christos static int afalg_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
     90  1.1.1.2  christos     const unsigned char *in, size_t inl);
     91      1.1  christos static int afalg_cipher_cleanup(EVP_CIPHER_CTX *ctx);
     92      1.1  christos static int afalg_chk_platform(void);
     93      1.1  christos 
     94      1.1  christos /* Engine Id and Name */
     95      1.1  christos static const char *engine_afalg_id = "afalg";
     96      1.1  christos static const char *engine_afalg_name = "AFALG engine support";
     97      1.1  christos 
     98      1.1  christos static int afalg_cipher_nids[] = {
     99      1.1  christos     NID_aes_128_cbc,
    100      1.1  christos     NID_aes_192_cbc,
    101      1.1  christos     NID_aes_256_cbc,
    102      1.1  christos };
    103      1.1  christos 
    104  1.1.1.2  christos static cbc_handles cbc_handle[] = { { AES_KEY_SIZE_128, NULL },
    105  1.1.1.2  christos     { AES_KEY_SIZE_192, NULL },
    106  1.1.1.2  christos     { AES_KEY_SIZE_256, NULL } };
    107      1.1  christos 
    108      1.1  christos static ossl_inline int io_setup(unsigned n, aio_context_t *ctx)
    109      1.1  christos {
    110      1.1  christos     return syscall(__NR_io_setup, n, ctx);
    111      1.1  christos }
    112      1.1  christos 
    113      1.1  christos static ossl_inline int eventfd(int n)
    114      1.1  christos {
    115      1.1  christos     return syscall(__NR_eventfd2, n, 0);
    116      1.1  christos }
    117      1.1  christos 
    118      1.1  christos static ossl_inline int io_destroy(aio_context_t ctx)
    119      1.1  christos {
    120      1.1  christos     return syscall(__NR_io_destroy, ctx);
    121      1.1  christos }
    122      1.1  christos 
    123      1.1  christos static ossl_inline int io_read(aio_context_t ctx, long n, struct iocb **iocb)
    124      1.1  christos {
    125      1.1  christos     return syscall(__NR_io_submit, ctx, n, iocb);
    126      1.1  christos }
    127      1.1  christos 
    128      1.1  christos /* A version of 'struct timespec' with 32-bit time_t and nanoseconds.  */
    129      1.1  christos struct __timespec32 {
    130  1.1.1.2  christos     __kernel_long_t tv_sec;
    131  1.1.1.2  christos     __kernel_long_t tv_nsec;
    132      1.1  christos };
    133      1.1  christos 
    134      1.1  christos static ossl_inline int io_getevents(aio_context_t ctx, long min, long max,
    135  1.1.1.2  christos     struct io_event *events,
    136  1.1.1.2  christos     struct timespec *timeout)
    137      1.1  christos {
    138      1.1  christos #if defined(__NR_io_pgetevents_time64)
    139      1.1  christos     /* Check if we are a 32-bit architecture with a 64-bit time_t */
    140      1.1  christos     if (sizeof(*timeout) != sizeof(struct __timespec32)) {
    141      1.1  christos         int ret = syscall(__NR_io_pgetevents_time64, ctx, min, max, events,
    142  1.1.1.2  christos             timeout, NULL);
    143      1.1  christos         if (ret == 0 || errno != ENOSYS)
    144      1.1  christos             return ret;
    145      1.1  christos     }
    146      1.1  christos #endif
    147      1.1  christos 
    148      1.1  christos #if defined(__NR_io_getevents)
    149      1.1  christos     if (sizeof(*timeout) == sizeof(struct __timespec32))
    150      1.1  christos         /*
    151      1.1  christos          * time_t matches our architecture length, we can just use
    152      1.1  christos          * __NR_io_getevents
    153      1.1  christos          */
    154      1.1  christos         return syscall(__NR_io_getevents, ctx, min, max, events, timeout);
    155      1.1  christos     else {
    156      1.1  christos         /*
    157      1.1  christos          * We don't have __NR_io_pgetevents_time64, but we are using a
    158      1.1  christos          * 64-bit time_t on a 32-bit architecture. If we can fit the
    159      1.1  christos          * timeout value in a 32-bit time_t, then let's do that
    160      1.1  christos          * and then use the __NR_io_getevents syscall.
    161      1.1  christos          */
    162      1.1  christos         if (timeout && timeout->tv_sec == (long)timeout->tv_sec) {
    163      1.1  christos             struct __timespec32 ts32;
    164      1.1  christos 
    165  1.1.1.2  christos             ts32.tv_sec = (__kernel_long_t)timeout->tv_sec;
    166  1.1.1.2  christos             ts32.tv_nsec = (__kernel_long_t)timeout->tv_nsec;
    167      1.1  christos 
    168      1.1  christos             return syscall(__NR_io_getevents, ctx, min, max, events, &ts32);
    169      1.1  christos         } else {
    170      1.1  christos             return syscall(__NR_io_getevents, ctx, min, max, events, NULL);
    171      1.1  christos         }
    172      1.1  christos     }
    173      1.1  christos #endif
    174      1.1  christos 
    175      1.1  christos     errno = ENOSYS;
    176      1.1  christos     return -1;
    177      1.1  christos }
    178      1.1  christos 
    179      1.1  christos static void afalg_waitfd_cleanup(ASYNC_WAIT_CTX *ctx, const void *key,
    180  1.1.1.2  christos     OSSL_ASYNC_FD waitfd, void *custom)
    181      1.1  christos {
    182      1.1  christos     close(waitfd);
    183      1.1  christos }
    184      1.1  christos 
    185      1.1  christos static int afalg_setup_async_event_notification(afalg_aio *aio)
    186      1.1  christos {
    187      1.1  christos     ASYNC_JOB *job;
    188      1.1  christos     ASYNC_WAIT_CTX *waitctx;
    189      1.1  christos     void *custom = NULL;
    190      1.1  christos     int ret;
    191      1.1  christos 
    192      1.1  christos     if ((job = ASYNC_get_current_job()) != NULL) {
    193      1.1  christos         /* Async mode */
    194      1.1  christos         waitctx = ASYNC_get_wait_ctx(job);
    195      1.1  christos         if (waitctx == NULL) {
    196      1.1  christos             ALG_WARN("%s(%d): ASYNC_get_wait_ctx error", __FILE__, __LINE__);
    197      1.1  christos             return 0;
    198      1.1  christos         }
    199      1.1  christos         /* Get waitfd from ASYNC_WAIT_CTX if it is already set */
    200      1.1  christos         ret = ASYNC_WAIT_CTX_get_fd(waitctx, engine_afalg_id,
    201  1.1.1.2  christos             &aio->efd, &custom);
    202      1.1  christos         if (ret == 0) {
    203      1.1  christos             /*
    204      1.1  christos              * waitfd is not set in ASYNC_WAIT_CTX, create a new one
    205      1.1  christos              * and set it. efd will be signaled when AIO operation completes
    206      1.1  christos              */
    207      1.1  christos             aio->efd = eventfd(0);
    208      1.1  christos             if (aio->efd == -1) {
    209      1.1  christos                 ALG_PERR("%s(%d): Failed to get eventfd : ", __FILE__,
    210  1.1.1.2  christos                     __LINE__);
    211      1.1  christos                 AFALGerr(AFALG_F_AFALG_SETUP_ASYNC_EVENT_NOTIFICATION,
    212  1.1.1.2  christos                     AFALG_R_EVENTFD_FAILED);
    213      1.1  christos                 return 0;
    214      1.1  christos             }
    215      1.1  christos             ret = ASYNC_WAIT_CTX_set_wait_fd(waitctx, engine_afalg_id,
    216  1.1.1.2  christos                 aio->efd, custom,
    217  1.1.1.2  christos                 afalg_waitfd_cleanup);
    218      1.1  christos             if (ret == 0) {
    219      1.1  christos                 ALG_WARN("%s(%d): Failed to set wait fd", __FILE__, __LINE__);
    220      1.1  christos                 close(aio->efd);
    221      1.1  christos                 return 0;
    222      1.1  christos             }
    223      1.1  christos             /* make fd non-blocking in async mode */
    224      1.1  christos             if (fcntl(aio->efd, F_SETFL, O_NONBLOCK) != 0) {
    225      1.1  christos                 ALG_WARN("%s(%d): Failed to set event fd as NONBLOCKING",
    226  1.1.1.2  christos                     __FILE__, __LINE__);
    227      1.1  christos             }
    228      1.1  christos         }
    229      1.1  christos         aio->mode = MODE_ASYNC;
    230      1.1  christos     } else {
    231      1.1  christos         /* Sync mode */
    232      1.1  christos         aio->efd = eventfd(0);
    233      1.1  christos         if (aio->efd == -1) {
    234      1.1  christos             ALG_PERR("%s(%d): Failed to get eventfd : ", __FILE__, __LINE__);
    235      1.1  christos             AFALGerr(AFALG_F_AFALG_SETUP_ASYNC_EVENT_NOTIFICATION,
    236  1.1.1.2  christos                 AFALG_R_EVENTFD_FAILED);
    237      1.1  christos             return 0;
    238      1.1  christos         }
    239      1.1  christos         aio->mode = MODE_SYNC;
    240      1.1  christos     }
    241      1.1  christos     return 1;
    242      1.1  christos }
    243      1.1  christos 
    244      1.1  christos static int afalg_init_aio(afalg_aio *aio)
    245      1.1  christos {
    246      1.1  christos     int r = -1;
    247      1.1  christos 
    248      1.1  christos     /* Initialise for AIO */
    249      1.1  christos     aio->aio_ctx = 0;
    250      1.1  christos     r = io_setup(MAX_INFLIGHTS, &aio->aio_ctx);
    251      1.1  christos     if (r < 0) {
    252      1.1  christos         ALG_PERR("%s(%d): io_setup error : ", __FILE__, __LINE__);
    253      1.1  christos         AFALGerr(AFALG_F_AFALG_INIT_AIO, AFALG_R_IO_SETUP_FAILED);
    254      1.1  christos         return 0;
    255      1.1  christos     }
    256      1.1  christos 
    257      1.1  christos     memset(aio->cbt, 0, sizeof(aio->cbt));
    258      1.1  christos     aio->efd = -1;
    259      1.1  christos     aio->mode = MODE_UNINIT;
    260      1.1  christos 
    261      1.1  christos     return 1;
    262      1.1  christos }
    263      1.1  christos 
    264      1.1  christos static int afalg_fin_cipher_aio(afalg_aio *aio, int sfd, unsigned char *buf,
    265  1.1.1.2  christos     size_t len)
    266      1.1  christos {
    267      1.1  christos     int r;
    268      1.1  christos     int retry = 0;
    269      1.1  christos     unsigned int done = 0;
    270      1.1  christos     struct iocb *cb;
    271      1.1  christos     struct timespec timeout;
    272      1.1  christos     struct io_event events[MAX_INFLIGHTS];
    273      1.1  christos     u_int64_t eval = 0;
    274      1.1  christos 
    275      1.1  christos     timeout.tv_sec = 0;
    276      1.1  christos     timeout.tv_nsec = 0;
    277      1.1  christos 
    278      1.1  christos     /* if efd has not been initialised yet do it here */
    279      1.1  christos     if (aio->mode == MODE_UNINIT) {
    280      1.1  christos         r = afalg_setup_async_event_notification(aio);
    281      1.1  christos         if (r == 0)
    282      1.1  christos             return 0;
    283      1.1  christos     }
    284      1.1  christos 
    285      1.1  christos     cb = &(aio->cbt[0 % MAX_INFLIGHTS]);
    286      1.1  christos     memset(cb, '\0', sizeof(*cb));
    287      1.1  christos     cb->aio_fildes = sfd;
    288      1.1  christos     cb->aio_lio_opcode = IOCB_CMD_PREAD;
    289      1.1  christos     /*
    290      1.1  christos      * The pointer has to be converted to unsigned value first to avoid
    291      1.1  christos      * sign extension on cast to 64 bit value in 32-bit builds
    292      1.1  christos      */
    293      1.1  christos     cb->aio_buf = (size_t)buf;
    294      1.1  christos     cb->aio_offset = 0;
    295      1.1  christos     cb->aio_data = 0;
    296      1.1  christos     cb->aio_nbytes = len;
    297      1.1  christos     cb->aio_flags = IOCB_FLAG_RESFD;
    298      1.1  christos     cb->aio_resfd = aio->efd;
    299      1.1  christos 
    300      1.1  christos     /*
    301      1.1  christos      * Perform AIO read on AFALG socket, this in turn performs an async
    302      1.1  christos      * crypto operation in kernel space
    303      1.1  christos      */
    304      1.1  christos     r = io_read(aio->aio_ctx, 1, &cb);
    305      1.1  christos     if (r < 0) {
    306      1.1  christos         ALG_PWARN("%s(%d): io_read failed : ", __FILE__, __LINE__);
    307      1.1  christos         return 0;
    308      1.1  christos     }
    309      1.1  christos 
    310      1.1  christos     do {
    311      1.1  christos         /* While AIO read is being performed pause job */
    312      1.1  christos         ASYNC_pause_job();
    313      1.1  christos 
    314      1.1  christos         /* Check for completion of AIO read */
    315      1.1  christos         r = read(aio->efd, &eval, sizeof(eval));
    316      1.1  christos         if (r < 0) {
    317      1.1  christos             if (errno == EAGAIN || errno == EWOULDBLOCK)
    318      1.1  christos                 continue;
    319      1.1  christos             ALG_PERR("%s(%d): read failed for event fd : ", __FILE__, __LINE__);
    320      1.1  christos             return 0;
    321      1.1  christos         } else if (r == 0 || eval <= 0) {
    322      1.1  christos             ALG_WARN("%s(%d): eventfd read %d bytes, eval = %lu\n", __FILE__,
    323  1.1.1.2  christos                 __LINE__, r, eval);
    324      1.1  christos         }
    325      1.1  christos         if (eval > 0) {
    326      1.1  christos 
    327      1.1  christos #ifdef OSSL_SANITIZE_MEMORY
    328      1.1  christos             /*
    329      1.1  christos              * In a memory sanitiser build, the changes to memory made by the
    330      1.1  christos              * system call aren't reliably detected.  By initialising the
    331      1.1  christos              * memory here, the sanitiser is told that they are okay.
    332      1.1  christos              */
    333      1.1  christos             memset(events, 0, sizeof(events));
    334      1.1  christos #endif
    335      1.1  christos 
    336      1.1  christos             /* Get results of AIO read */
    337      1.1  christos             r = io_getevents(aio->aio_ctx, 1, MAX_INFLIGHTS,
    338  1.1.1.2  christos                 events, &timeout);
    339      1.1  christos             if (r > 0) {
    340      1.1  christos                 /*
    341      1.1  christos                  * events.res indicates the actual status of the operation.
    342      1.1  christos                  * Handle the error condition first.
    343      1.1  christos                  */
    344      1.1  christos                 if (events[0].res < 0) {
    345      1.1  christos                     /*
    346      1.1  christos                      * Underlying operation cannot be completed at the time
    347      1.1  christos                      * of previous submission. Resubmit for the operation.
    348      1.1  christos                      */
    349      1.1  christos                     if (events[0].res == -EBUSY && retry++ < 3) {
    350      1.1  christos                         r = io_read(aio->aio_ctx, 1, &cb);
    351      1.1  christos                         if (r < 0) {
    352      1.1  christos                             ALG_PERR("%s(%d): retry %d for io_read failed : ",
    353  1.1.1.2  christos                                 __FILE__, __LINE__, retry);
    354      1.1  christos                             return 0;
    355      1.1  christos                         }
    356      1.1  christos                         continue;
    357      1.1  christos                     } else {
    358      1.1  christos                         char strbuf[32];
    359      1.1  christos                         /*
    360      1.1  christos                          * sometimes __s64 is defined as long long int
    361      1.1  christos                          * but on some archs ( like mips64 or powerpc64 ) it's just long int
    362      1.1  christos                          *
    363      1.1  christos                          * to be able to use BIO_snprintf() with %lld without warnings
    364      1.1  christos                          * copy events[0].res to an long long int variable
    365      1.1  christos                          *
    366      1.1  christos                          * because long long int should always be at least 64 bit this should work
    367      1.1  christos                          */
    368      1.1  christos                         long long int op_ret = events[0].res;
    369      1.1  christos 
    370      1.1  christos                         /*
    371      1.1  christos                          * Retries exceed for -EBUSY or unrecoverable error
    372      1.1  christos                          * condition for this instance of operation.
    373      1.1  christos                          */
    374  1.1.1.2  christos                         ALG_WARN("%s(%d): Crypto Operation failed with code %lld\n",
    375  1.1.1.2  christos                             __FILE__, __LINE__, events[0].res);
    376      1.1  christos                         BIO_snprintf(strbuf, sizeof(strbuf), "%lld", op_ret);
    377      1.1  christos                         switch (events[0].res) {
    378      1.1  christos                         case -ENOMEM:
    379      1.1  christos                             AFALGerr(0, AFALG_R_KERNEL_OP_FAILED);
    380      1.1  christos                             ERR_add_error_data(3, "-ENOMEM ( code ", strbuf, " )");
    381      1.1  christos                             break;
    382      1.1  christos                         default:
    383      1.1  christos                             AFALGerr(0, AFALG_R_KERNEL_OP_FAILED);
    384      1.1  christos                             ERR_add_error_data(2, "code ", strbuf);
    385      1.1  christos                             break;
    386      1.1  christos                         }
    387      1.1  christos                         return 0;
    388      1.1  christos                     }
    389      1.1  christos                 }
    390      1.1  christos                 /* Operation successful. */
    391      1.1  christos                 done = 1;
    392      1.1  christos             } else if (r < 0) {
    393      1.1  christos                 ALG_PERR("%s(%d): io_getevents failed : ", __FILE__, __LINE__);
    394      1.1  christos                 return 0;
    395      1.1  christos             } else {
    396      1.1  christos                 ALG_WARN("%s(%d): io_geteventd read 0 bytes\n", __FILE__,
    397  1.1.1.2  christos                     __LINE__);
    398      1.1  christos             }
    399      1.1  christos         }
    400      1.1  christos     } while (!done);
    401      1.1  christos 
    402      1.1  christos     return 1;
    403      1.1  christos }
    404      1.1  christos 
    405      1.1  christos static ossl_inline void afalg_set_op_sk(struct cmsghdr *cmsg,
    406  1.1.1.2  christos     const ALG_OP_TYPE op)
    407      1.1  christos {
    408      1.1  christos     cmsg->cmsg_level = SOL_ALG;
    409      1.1  christos     cmsg->cmsg_type = ALG_SET_OP;
    410      1.1  christos     cmsg->cmsg_len = CMSG_LEN(ALG_OP_LEN);
    411      1.1  christos     memcpy(CMSG_DATA(cmsg), &op, ALG_OP_LEN);
    412      1.1  christos }
    413      1.1  christos 
    414      1.1  christos static void afalg_set_iv_sk(struct cmsghdr *cmsg, const unsigned char *iv,
    415  1.1.1.2  christos     const unsigned int len)
    416      1.1  christos {
    417      1.1  christos     struct af_alg_iv *aiv;
    418      1.1  christos 
    419      1.1  christos     cmsg->cmsg_level = SOL_ALG;
    420      1.1  christos     cmsg->cmsg_type = ALG_SET_IV;
    421      1.1  christos     cmsg->cmsg_len = CMSG_LEN(ALG_IV_LEN(len));
    422      1.1  christos     aiv = (struct af_alg_iv *)CMSG_DATA(cmsg);
    423      1.1  christos     aiv->ivlen = len;
    424      1.1  christos     memcpy(aiv->iv, iv, len);
    425      1.1  christos }
    426      1.1  christos 
    427      1.1  christos static ossl_inline int afalg_set_key(afalg_ctx *actx, const unsigned char *key,
    428  1.1.1.2  christos     const int klen)
    429      1.1  christos {
    430      1.1  christos     int ret;
    431      1.1  christos     ret = setsockopt(actx->bfd, SOL_ALG, ALG_SET_KEY, key, klen);
    432      1.1  christos     if (ret < 0) {
    433      1.1  christos         ALG_PERR("%s(%d): Failed to set socket option : ", __FILE__, __LINE__);
    434      1.1  christos         AFALGerr(AFALG_F_AFALG_SET_KEY, AFALG_R_SOCKET_SET_KEY_FAILED);
    435      1.1  christos         return 0;
    436      1.1  christos     }
    437      1.1  christos     return 1;
    438      1.1  christos }
    439      1.1  christos 
    440      1.1  christos static int afalg_create_sk(afalg_ctx *actx, const char *ciphertype,
    441  1.1.1.2  christos     const char *ciphername)
    442      1.1  christos {
    443      1.1  christos     struct sockaddr_alg sa;
    444      1.1  christos     int r = -1;
    445      1.1  christos 
    446      1.1  christos     actx->bfd = actx->sfd = -1;
    447      1.1  christos 
    448      1.1  christos     memset(&sa, 0, sizeof(sa));
    449      1.1  christos     sa.salg_family = AF_ALG;
    450  1.1.1.2  christos     OPENSSL_strlcpy((char *)sa.salg_type, ciphertype, sizeof(sa.salg_type));
    451  1.1.1.2  christos     OPENSSL_strlcpy((char *)sa.salg_name, ciphername, sizeof(sa.salg_name));
    452      1.1  christos 
    453      1.1  christos     actx->bfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
    454      1.1  christos     if (actx->bfd == -1) {
    455      1.1  christos         ALG_PERR("%s(%d): Failed to open socket : ", __FILE__, __LINE__);
    456      1.1  christos         AFALGerr(AFALG_F_AFALG_CREATE_SK, AFALG_R_SOCKET_CREATE_FAILED);
    457      1.1  christos         goto err;
    458      1.1  christos     }
    459      1.1  christos 
    460      1.1  christos     r = bind(actx->bfd, (struct sockaddr *)&sa, sizeof(sa));
    461      1.1  christos     if (r < 0) {
    462      1.1  christos         ALG_PERR("%s(%d): Failed to bind socket : ", __FILE__, __LINE__);
    463      1.1  christos         AFALGerr(AFALG_F_AFALG_CREATE_SK, AFALG_R_SOCKET_BIND_FAILED);
    464      1.1  christos         goto err;
    465      1.1  christos     }
    466      1.1  christos 
    467      1.1  christos     actx->sfd = accept(actx->bfd, NULL, 0);
    468      1.1  christos     if (actx->sfd < 0) {
    469      1.1  christos         ALG_PERR("%s(%d): Socket Accept Failed : ", __FILE__, __LINE__);
    470      1.1  christos         AFALGerr(AFALG_F_AFALG_CREATE_SK, AFALG_R_SOCKET_ACCEPT_FAILED);
    471      1.1  christos         goto err;
    472      1.1  christos     }
    473      1.1  christos 
    474      1.1  christos     return 1;
    475      1.1  christos 
    476  1.1.1.2  christos err:
    477      1.1  christos     if (actx->bfd >= 0)
    478      1.1  christos         close(actx->bfd);
    479      1.1  christos     if (actx->sfd >= 0)
    480      1.1  christos         close(actx->sfd);
    481      1.1  christos     actx->bfd = actx->sfd = -1;
    482      1.1  christos     return 0;
    483      1.1  christos }
    484      1.1  christos 
    485      1.1  christos static int afalg_start_cipher_sk(afalg_ctx *actx, const unsigned char *in,
    486  1.1.1.2  christos     size_t inl, const unsigned char *iv,
    487  1.1.1.2  christos     unsigned int enc)
    488      1.1  christos {
    489      1.1  christos     struct msghdr msg;
    490      1.1  christos     struct cmsghdr *cmsg;
    491      1.1  christos     struct iovec iov;
    492      1.1  christos     ssize_t sbytes;
    493  1.1.1.2  christos #ifdef ALG_ZERO_COPY
    494      1.1  christos     int ret;
    495  1.1.1.2  christos #endif
    496      1.1  christos     char cbuf[CMSG_SPACE(ALG_IV_LEN(ALG_AES_IV_LEN)) + CMSG_SPACE(ALG_OP_LEN)];
    497      1.1  christos 
    498      1.1  christos     memset(&msg, 0, sizeof(msg));
    499      1.1  christos     memset(cbuf, 0, sizeof(cbuf));
    500      1.1  christos     msg.msg_control = cbuf;
    501      1.1  christos     msg.msg_controllen = sizeof(cbuf);
    502      1.1  christos 
    503      1.1  christos     /*
    504      1.1  christos      * cipher direction (i.e. encrypt or decrypt) and iv are sent to the
    505      1.1  christos      * kernel as part of sendmsg()'s ancillary data
    506      1.1  christos      */
    507      1.1  christos     cmsg = CMSG_FIRSTHDR(&msg);
    508      1.1  christos     afalg_set_op_sk(cmsg, enc);
    509      1.1  christos     cmsg = CMSG_NXTHDR(&msg, cmsg);
    510      1.1  christos     afalg_set_iv_sk(cmsg, iv, ALG_AES_IV_LEN);
    511      1.1  christos 
    512      1.1  christos     /* iov that describes input data */
    513      1.1  christos     iov.iov_base = (unsigned char *)in;
    514      1.1  christos     iov.iov_len = inl;
    515      1.1  christos 
    516      1.1  christos     msg.msg_flags = MSG_MORE;
    517      1.1  christos 
    518  1.1.1.2  christos #ifdef ALG_ZERO_COPY
    519      1.1  christos     /*
    520      1.1  christos      * ZERO_COPY mode
    521      1.1  christos      * Works best when buffer is 4k aligned
    522      1.1  christos      * OPENS: out of place processing (i.e. out != in)
    523      1.1  christos      */
    524      1.1  christos 
    525      1.1  christos     /* Input data is not sent as part of call to sendmsg() */
    526      1.1  christos     msg.msg_iovlen = 0;
    527      1.1  christos     msg.msg_iov = NULL;
    528      1.1  christos 
    529      1.1  christos     /* Sendmsg() sends iv and cipher direction to the kernel */
    530      1.1  christos     sbytes = sendmsg(actx->sfd, &msg, 0);
    531      1.1  christos     if (sbytes < 0) {
    532      1.1  christos         ALG_PERR("%s(%d): sendmsg failed for zero copy cipher operation : ",
    533  1.1.1.2  christos             __FILE__, __LINE__);
    534      1.1  christos         return 0;
    535      1.1  christos     }
    536      1.1  christos 
    537      1.1  christos     /*
    538      1.1  christos      * vmsplice and splice are used to pin the user space input buffer for
    539      1.1  christos      * kernel space processing avoiding copies from user to kernel space
    540      1.1  christos      */
    541      1.1  christos     ret = vmsplice(actx->zc_pipe[1], &iov, 1, SPLICE_F_GIFT);
    542      1.1  christos     if (ret < 0) {
    543      1.1  christos         ALG_PERR("%s(%d): vmsplice failed : ", __FILE__, __LINE__);
    544      1.1  christos         return 0;
    545      1.1  christos     }
    546      1.1  christos 
    547      1.1  christos     ret = splice(actx->zc_pipe[0], NULL, actx->sfd, NULL, inl, 0);
    548      1.1  christos     if (ret < 0) {
    549      1.1  christos         ALG_PERR("%s(%d): splice failed : ", __FILE__, __LINE__);
    550      1.1  christos         return 0;
    551      1.1  christos     }
    552  1.1.1.2  christos #else
    553      1.1  christos     msg.msg_iovlen = 1;
    554      1.1  christos     msg.msg_iov = &iov;
    555      1.1  christos 
    556      1.1  christos     /* Sendmsg() sends iv, cipher direction and input data to the kernel */
    557      1.1  christos     sbytes = sendmsg(actx->sfd, &msg, 0);
    558      1.1  christos     if (sbytes < 0) {
    559      1.1  christos         ALG_PERR("%s(%d): sendmsg failed for cipher operation : ", __FILE__,
    560  1.1.1.2  christos             __LINE__);
    561      1.1  christos         return 0;
    562      1.1  christos     }
    563      1.1  christos 
    564  1.1.1.2  christos     if (sbytes != (ssize_t)inl) {
    565      1.1  christos         ALG_WARN("Cipher operation send bytes %zd != inlen %zd\n", sbytes,
    566  1.1.1.2  christos             inl);
    567      1.1  christos         return 0;
    568      1.1  christos     }
    569  1.1.1.2  christos #endif
    570      1.1  christos 
    571      1.1  christos     return 1;
    572      1.1  christos }
    573      1.1  christos 
    574      1.1  christos static int afalg_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
    575  1.1.1.2  christos     const unsigned char *iv, int enc)
    576      1.1  christos {
    577      1.1  christos     int ciphertype;
    578      1.1  christos     int ret, len;
    579      1.1  christos     afalg_ctx *actx;
    580      1.1  christos     const char *ciphername;
    581      1.1  christos 
    582      1.1  christos     if (ctx == NULL || key == NULL) {
    583      1.1  christos         ALG_WARN("%s(%d): Null Parameter\n", __FILE__, __LINE__);
    584      1.1  christos         return 0;
    585      1.1  christos     }
    586      1.1  christos 
    587      1.1  christos     if (EVP_CIPHER_CTX_get0_cipher(ctx) == NULL) {
    588      1.1  christos         ALG_WARN("%s(%d): Cipher object NULL\n", __FILE__, __LINE__);
    589      1.1  christos         return 0;
    590      1.1  christos     }
    591      1.1  christos 
    592      1.1  christos     actx = EVP_CIPHER_CTX_get_cipher_data(ctx);
    593      1.1  christos     if (actx == NULL) {
    594      1.1  christos         ALG_WARN("%s(%d): Cipher data NULL\n", __FILE__, __LINE__);
    595      1.1  christos         return 0;
    596      1.1  christos     }
    597      1.1  christos 
    598      1.1  christos     ciphertype = EVP_CIPHER_CTX_get_nid(ctx);
    599      1.1  christos     switch (ciphertype) {
    600      1.1  christos     case NID_aes_128_cbc:
    601      1.1  christos     case NID_aes_192_cbc:
    602      1.1  christos     case NID_aes_256_cbc:
    603      1.1  christos         ciphername = "cbc(aes)";
    604      1.1  christos         break;
    605      1.1  christos     default:
    606      1.1  christos         ALG_WARN("%s(%d): Unsupported Cipher type %d\n", __FILE__, __LINE__,
    607  1.1.1.2  christos             ciphertype);
    608      1.1  christos         return 0;
    609      1.1  christos     }
    610      1.1  christos 
    611      1.1  christos     if (ALG_AES_IV_LEN != EVP_CIPHER_CTX_get_iv_length(ctx)) {
    612      1.1  christos         ALG_WARN("%s(%d): Unsupported IV length :%d\n", __FILE__, __LINE__,
    613  1.1.1.2  christos             EVP_CIPHER_CTX_get_iv_length(ctx));
    614      1.1  christos         return 0;
    615      1.1  christos     }
    616      1.1  christos 
    617      1.1  christos     /* Setup AFALG socket for crypto processing */
    618      1.1  christos     ret = afalg_create_sk(actx, "skcipher", ciphername);
    619      1.1  christos     if (ret < 1)
    620      1.1  christos         return 0;
    621      1.1  christos 
    622      1.1  christos     if ((len = EVP_CIPHER_CTX_get_key_length(ctx)) <= 0)
    623      1.1  christos         goto err;
    624      1.1  christos     ret = afalg_set_key(actx, key, len);
    625      1.1  christos     if (ret < 1)
    626      1.1  christos         goto err;
    627      1.1  christos 
    628      1.1  christos     /* Setup AIO ctx to allow async AFALG crypto processing */
    629      1.1  christos     if (afalg_init_aio(&actx->aio) == 0)
    630      1.1  christos         goto err;
    631      1.1  christos 
    632  1.1.1.2  christos #ifdef ALG_ZERO_COPY
    633      1.1  christos     pipe(actx->zc_pipe);
    634  1.1.1.2  christos #endif
    635      1.1  christos 
    636      1.1  christos     actx->init_done = MAGIC_INIT_NUM;
    637      1.1  christos 
    638      1.1  christos     return 1;
    639      1.1  christos 
    640      1.1  christos err:
    641      1.1  christos     close(actx->sfd);
    642      1.1  christos     close(actx->bfd);
    643      1.1  christos     return 0;
    644      1.1  christos }
    645      1.1  christos 
    646      1.1  christos static int afalg_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
    647  1.1.1.2  christos     const unsigned char *in, size_t inl)
    648      1.1  christos {
    649      1.1  christos     afalg_ctx *actx;
    650      1.1  christos     int ret;
    651      1.1  christos     char nxtiv[ALG_AES_IV_LEN] = { 0 };
    652      1.1  christos 
    653      1.1  christos     if (ctx == NULL || out == NULL || in == NULL) {
    654      1.1  christos         ALG_WARN("NULL parameter passed to function %s(%d)\n", __FILE__,
    655  1.1.1.2  christos             __LINE__);
    656      1.1  christos         return 0;
    657      1.1  christos     }
    658      1.1  christos 
    659  1.1.1.2  christos     actx = (afalg_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
    660      1.1  christos     if (actx == NULL || actx->init_done != MAGIC_INIT_NUM) {
    661      1.1  christos         ALG_WARN("%s afalg ctx passed\n",
    662  1.1.1.2  christos             ctx == NULL ? "NULL" : "Uninitialised");
    663      1.1  christos         return 0;
    664      1.1  christos     }
    665      1.1  christos 
    666      1.1  christos     /*
    667      1.1  christos      * set iv now for decrypt operation as the input buffer can be
    668      1.1  christos      * overwritten for inplace operation where in = out.
    669      1.1  christos      */
    670      1.1  christos     if (EVP_CIPHER_CTX_is_encrypting(ctx) == 0) {
    671      1.1  christos         memcpy(nxtiv, in + (inl - ALG_AES_IV_LEN), ALG_AES_IV_LEN);
    672      1.1  christos     }
    673      1.1  christos 
    674      1.1  christos     /* Send input data to kernel space */
    675      1.1  christos     ret = afalg_start_cipher_sk(actx, (unsigned char *)in, inl,
    676  1.1.1.2  christos         EVP_CIPHER_CTX_iv(ctx),
    677  1.1.1.2  christos         EVP_CIPHER_CTX_is_encrypting(ctx));
    678      1.1  christos     if (ret < 1) {
    679      1.1  christos         return 0;
    680      1.1  christos     }
    681      1.1  christos 
    682      1.1  christos     /* Perform async crypto operation in kernel space */
    683      1.1  christos     ret = afalg_fin_cipher_aio(&actx->aio, actx->sfd, out, inl);
    684      1.1  christos     if (ret < 1)
    685      1.1  christos         return 0;
    686      1.1  christos 
    687      1.1  christos     if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
    688      1.1  christos         memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), out + (inl - ALG_AES_IV_LEN),
    689  1.1.1.2  christos             ALG_AES_IV_LEN);
    690      1.1  christos     } else {
    691      1.1  christos         memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), nxtiv, ALG_AES_IV_LEN);
    692      1.1  christos     }
    693      1.1  christos 
    694      1.1  christos     return 1;
    695      1.1  christos }
    696      1.1  christos 
    697      1.1  christos static int afalg_cipher_cleanup(EVP_CIPHER_CTX *ctx)
    698      1.1  christos {
    699      1.1  christos     afalg_ctx *actx;
    700      1.1  christos 
    701      1.1  christos     if (ctx == NULL) {
    702      1.1  christos         ALG_WARN("NULL parameter passed to function %s(%d)\n", __FILE__,
    703  1.1.1.2  christos             __LINE__);
    704      1.1  christos         return 0;
    705      1.1  christos     }
    706      1.1  christos 
    707  1.1.1.2  christos     actx = (afalg_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
    708      1.1  christos     if (actx == NULL || actx->init_done != MAGIC_INIT_NUM)
    709      1.1  christos         return 1;
    710      1.1  christos 
    711      1.1  christos     close(actx->sfd);
    712      1.1  christos     close(actx->bfd);
    713  1.1.1.2  christos #ifdef ALG_ZERO_COPY
    714      1.1  christos     close(actx->zc_pipe[0]);
    715      1.1  christos     close(actx->zc_pipe[1]);
    716  1.1.1.2  christos #endif
    717      1.1  christos     /* close efd in sync mode, async mode is closed in afalg_waitfd_cleanup() */
    718      1.1  christos     if (actx->aio.mode == MODE_SYNC)
    719      1.1  christos         close(actx->aio.efd);
    720      1.1  christos     io_destroy(actx->aio.aio_ctx);
    721      1.1  christos 
    722      1.1  christos     return 1;
    723      1.1  christos }
    724      1.1  christos 
    725      1.1  christos static cbc_handles *get_cipher_handle(int nid)
    726      1.1  christos {
    727      1.1  christos     switch (nid) {
    728      1.1  christos     case NID_aes_128_cbc:
    729      1.1  christos         return &cbc_handle[AES_CBC_128];
    730      1.1  christos     case NID_aes_192_cbc:
    731      1.1  christos         return &cbc_handle[AES_CBC_192];
    732      1.1  christos     case NID_aes_256_cbc:
    733      1.1  christos         return &cbc_handle[AES_CBC_256];
    734      1.1  christos     default:
    735      1.1  christos         return NULL;
    736      1.1  christos     }
    737      1.1  christos }
    738      1.1  christos 
    739      1.1  christos static const EVP_CIPHER *afalg_aes_cbc(int nid)
    740      1.1  christos {
    741      1.1  christos     cbc_handles *cipher_handle = get_cipher_handle(nid);
    742      1.1  christos 
    743      1.1  christos     if (cipher_handle == NULL)
    744  1.1.1.2  christos         return NULL;
    745      1.1  christos     if (cipher_handle->_hidden == NULL
    746  1.1.1.2  christos         && ((cipher_handle->_hidden = EVP_CIPHER_meth_new(nid,
    747  1.1.1.2  christos                  AES_BLOCK_SIZE,
    748  1.1.1.2  christos                  cipher_handle->key_size))
    749  1.1.1.2  christos                 == NULL
    750  1.1.1.2  christos             || !EVP_CIPHER_meth_set_iv_length(cipher_handle->_hidden,
    751  1.1.1.2  christos                 AES_IV_LEN)
    752  1.1.1.2  christos             || !EVP_CIPHER_meth_set_flags(cipher_handle->_hidden,
    753  1.1.1.2  christos                 EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1)
    754  1.1.1.2  christos             || !EVP_CIPHER_meth_set_init(cipher_handle->_hidden,
    755  1.1.1.2  christos                 afalg_cipher_init)
    756  1.1.1.2  christos             || !EVP_CIPHER_meth_set_do_cipher(cipher_handle->_hidden,
    757  1.1.1.2  christos                 afalg_do_cipher)
    758  1.1.1.2  christos             || !EVP_CIPHER_meth_set_cleanup(cipher_handle->_hidden,
    759  1.1.1.2  christos                 afalg_cipher_cleanup)
    760  1.1.1.2  christos             || !EVP_CIPHER_meth_set_impl_ctx_size(cipher_handle->_hidden,
    761  1.1.1.2  christos                 sizeof(afalg_ctx)))) {
    762      1.1  christos         EVP_CIPHER_meth_free(cipher_handle->_hidden);
    763  1.1.1.2  christos         cipher_handle->_hidden = NULL;
    764      1.1  christos     }
    765      1.1  christos     return cipher_handle->_hidden;
    766      1.1  christos }
    767      1.1  christos 
    768      1.1  christos static int afalg_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
    769  1.1.1.2  christos     const int **nids, int nid)
    770      1.1  christos {
    771      1.1  christos     int r = 1;
    772      1.1  christos 
    773      1.1  christos     if (cipher == NULL) {
    774      1.1  christos         *nids = afalg_cipher_nids;
    775      1.1  christos         return OSSL_NELEM(afalg_cipher_nids);
    776      1.1  christos     }
    777      1.1  christos 
    778      1.1  christos     switch (nid) {
    779      1.1  christos     case NID_aes_128_cbc:
    780      1.1  christos     case NID_aes_192_cbc:
    781      1.1  christos     case NID_aes_256_cbc:
    782      1.1  christos         *cipher = afalg_aes_cbc(nid);
    783      1.1  christos         break;
    784      1.1  christos     default:
    785      1.1  christos         *cipher = NULL;
    786      1.1  christos         r = 0;
    787      1.1  christos     }
    788      1.1  christos     return r;
    789      1.1  christos }
    790      1.1  christos 
    791      1.1  christos static int bind_afalg(ENGINE *e)
    792      1.1  christos {
    793      1.1  christos     /* Ensure the afalg error handling is set up */
    794      1.1  christos     unsigned short i;
    795      1.1  christos     ERR_load_AFALG_strings();
    796      1.1  christos 
    797      1.1  christos     if (!ENGINE_set_id(e, engine_afalg_id)
    798      1.1  christos         || !ENGINE_set_name(e, engine_afalg_name)
    799      1.1  christos         || !ENGINE_set_destroy_function(e, afalg_destroy)
    800      1.1  christos         || !ENGINE_set_init_function(e, afalg_init)
    801      1.1  christos         || !ENGINE_set_finish_function(e, afalg_finish)) {
    802      1.1  christos         AFALGerr(AFALG_F_BIND_AFALG, AFALG_R_INIT_FAILED);
    803      1.1  christos         return 0;
    804      1.1  christos     }
    805      1.1  christos 
    806      1.1  christos     /*
    807      1.1  christos      * Create _hidden_aes_xxx_cbc by calling afalg_aes_xxx_cbc
    808      1.1  christos      * now, as bind_aflag can only be called by one thread at a
    809      1.1  christos      * time.
    810      1.1  christos      */
    811      1.1  christos     for (i = 0; i < OSSL_NELEM(afalg_cipher_nids); i++) {
    812      1.1  christos         if (afalg_aes_cbc(afalg_cipher_nids[i]) == NULL) {
    813      1.1  christos             AFALGerr(AFALG_F_BIND_AFALG, AFALG_R_INIT_FAILED);
    814      1.1  christos             return 0;
    815      1.1  christos         }
    816      1.1  christos     }
    817      1.1  christos 
    818      1.1  christos     if (!ENGINE_set_ciphers(e, afalg_ciphers)) {
    819      1.1  christos         AFALGerr(AFALG_F_BIND_AFALG, AFALG_R_INIT_FAILED);
    820      1.1  christos         return 0;
    821      1.1  christos     }
    822      1.1  christos 
    823      1.1  christos     return 1;
    824      1.1  christos }
    825      1.1  christos 
    826  1.1.1.2  christos #ifndef OPENSSL_NO_DYNAMIC_ENGINE
    827      1.1  christos static int bind_helper(ENGINE *e, const char *id)
    828      1.1  christos {
    829      1.1  christos     if (id && (strcmp(id, engine_afalg_id) != 0))
    830      1.1  christos         return 0;
    831      1.1  christos 
    832      1.1  christos     if (!afalg_chk_platform())
    833      1.1  christos         return 0;
    834      1.1  christos 
    835      1.1  christos     if (!bind_afalg(e)) {
    836      1.1  christos         afalg_destroy(e);
    837      1.1  christos         return 0;
    838      1.1  christos     }
    839      1.1  christos     return 1;
    840      1.1  christos }
    841      1.1  christos 
    842      1.1  christos IMPLEMENT_DYNAMIC_CHECK_FN()
    843  1.1.1.2  christos IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
    844  1.1.1.2  christos #endif
    845      1.1  christos 
    846      1.1  christos static int afalg_chk_platform(void)
    847      1.1  christos {
    848      1.1  christos     int ret;
    849      1.1  christos     int i;
    850      1.1  christos     int kver[3] = { -1, -1, -1 };
    851      1.1  christos     int sock;
    852      1.1  christos     char *str;
    853      1.1  christos     struct utsname ut;
    854      1.1  christos 
    855      1.1  christos     ret = uname(&ut);
    856      1.1  christos     if (ret != 0) {
    857      1.1  christos         AFALGerr(AFALG_F_AFALG_CHK_PLATFORM,
    858  1.1.1.2  christos             AFALG_R_FAILED_TO_GET_PLATFORM_INFO);
    859      1.1  christos         return 0;
    860      1.1  christos     }
    861      1.1  christos 
    862      1.1  christos     str = strtok(ut.release, ".");
    863      1.1  christos     for (i = 0; i < 3 && str != NULL; i++) {
    864      1.1  christos         kver[i] = atoi(str);
    865      1.1  christos         str = strtok(NULL, ".");
    866      1.1  christos     }
    867      1.1  christos 
    868      1.1  christos     if (KERNEL_VERSION(kver[0], kver[1], kver[2])
    869      1.1  christos         < KERNEL_VERSION(K_MAJ, K_MIN1, K_MIN2)) {
    870      1.1  christos         ALG_ERR("ASYNC AFALG not supported this kernel(%d.%d.%d)\n",
    871  1.1.1.2  christos             kver[0], kver[1], kver[2]);
    872      1.1  christos         ALG_ERR("ASYNC AFALG requires kernel version %d.%d.%d or later\n",
    873  1.1.1.2  christos             K_MAJ, K_MIN1, K_MIN2);
    874      1.1  christos         AFALGerr(AFALG_F_AFALG_CHK_PLATFORM,
    875  1.1.1.2  christos             AFALG_R_KERNEL_DOES_NOT_SUPPORT_ASYNC_AFALG);
    876      1.1  christos         return 0;
    877      1.1  christos     }
    878      1.1  christos 
    879      1.1  christos     /* Test if we can actually create an AF_ALG socket */
    880      1.1  christos     sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
    881      1.1  christos     if (sock == -1) {
    882      1.1  christos         AFALGerr(AFALG_F_AFALG_CHK_PLATFORM, AFALG_R_SOCKET_CREATE_FAILED);
    883      1.1  christos         return 0;
    884      1.1  christos     }
    885      1.1  christos     close(sock);
    886      1.1  christos 
    887      1.1  christos     return 1;
    888      1.1  christos }
    889      1.1  christos 
    890  1.1.1.2  christos #ifdef OPENSSL_NO_DYNAMIC_ENGINE
    891      1.1  christos static ENGINE *engine_afalg(void)
    892      1.1  christos {
    893      1.1  christos     ENGINE *ret = ENGINE_new();
    894      1.1  christos     if (ret == NULL)
    895      1.1  christos         return NULL;
    896      1.1  christos     if (!bind_afalg(ret)) {
    897      1.1  christos         ENGINE_free(ret);
    898      1.1  christos         return NULL;
    899      1.1  christos     }
    900      1.1  christos     return ret;
    901      1.1  christos }
    902      1.1  christos 
    903      1.1  christos void engine_load_afalg_int(void)
    904      1.1  christos {
    905      1.1  christos     ENGINE *toadd;
    906      1.1  christos 
    907      1.1  christos     if (!afalg_chk_platform())
    908      1.1  christos         return;
    909      1.1  christos 
    910      1.1  christos     toadd = engine_afalg();
    911      1.1  christos     if (toadd == NULL)
    912      1.1  christos         return;
    913      1.1  christos     ERR_set_mark();
    914      1.1  christos     ENGINE_add(toadd);
    915      1.1  christos     /*
    916      1.1  christos      * If the "add" worked, it gets a structural reference. So either way, we
    917      1.1  christos      * release our just-created reference.
    918      1.1  christos      */
    919      1.1  christos     ENGINE_free(toadd);
    920      1.1  christos     /*
    921      1.1  christos      * If the "add" didn't work, it was probably a conflict because it was
    922      1.1  christos      * already added (eg. someone calling ENGINE_load_blah then calling
    923      1.1  christos      * ENGINE_load_builtin_engines() perhaps).
    924      1.1  christos      */
    925      1.1  christos     ERR_pop_to_mark();
    926      1.1  christos }
    927  1.1.1.2  christos #endif
    928      1.1  christos 
    929      1.1  christos static int afalg_init(ENGINE *e)
    930      1.1  christos {
    931      1.1  christos     return 1;
    932      1.1  christos }
    933      1.1  christos 
    934      1.1  christos static int afalg_finish(ENGINE *e)
    935      1.1  christos {
    936      1.1  christos     return 1;
    937      1.1  christos }
    938      1.1  christos 
    939      1.1  christos static int free_cbc(void)
    940      1.1  christos {
    941      1.1  christos     short unsigned int i;
    942      1.1  christos     for (i = 0; i < OSSL_NELEM(afalg_cipher_nids); i++) {
    943      1.1  christos         EVP_CIPHER_meth_free(cbc_handle[i]._hidden);
    944      1.1  christos         cbc_handle[i]._hidden = NULL;
    945      1.1  christos     }
    946      1.1  christos     return 1;
    947      1.1  christos }
    948      1.1  christos 
    949      1.1  christos static int afalg_destroy(ENGINE *e)
    950      1.1  christos {
    951      1.1  christos     ERR_unload_AFALG_strings();
    952      1.1  christos     free_cbc();
    953      1.1  christos     return 1;
    954      1.1  christos }
    955      1.1  christos 
    956  1.1.1.2  christos #endif /* KERNEL VERSION */
    957