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