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