1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
|
/*
* Copyright (C) 2016 - 2022, Stephan Mueller <smueller@chronox.de>
*
* License: see COPYING file in root directory
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
* WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
#ifndef INTERNAL_H
#define INTERNAL_H
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/aio_abi.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/uio.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <stdio.h>
#include <linux/if_alg.h>
#include "atomic.h"
#include "kcapi.h"
#ifdef __cplusplus
extern "C"
{
#endif
/* remove once in if_alg.h */
#ifndef ALG_SET_AEAD_ASSOCLEN
#define ALG_SET_AEAD_ASSOCLEN 4
#endif
#ifndef ALG_SET_AEAD_AUTHSIZE
#define ALG_SET_AEAD_AUTHSIZE 5
#endif
#ifndef ALG_SET_DRBG_ENTROPY
#define ALG_SET_DRBG_ENTROPY 6
#endif
#ifndef ALG_SET_PUBKEY
#define ALG_SET_PUBKEY 7
#endif
#ifndef ALG_SET_DH_PARAMETERS
#define ALG_SET_DH_PARAMETERS 8
#endif
#ifndef ALG_SET_ECDH_CURVE
#define ALG_SET_ECDH_CURVE 9
#endif
#ifndef ALG_OP_SIGN
#define ALG_OP_SIGN 2
#endif
#ifndef ALG_OP_VERIFY
#define ALG_OP_VERIFY 3
#endif
#ifndef ALG_OP_KEYGEN
#define ALG_OP_KEYGEN 4
#endif
#ifndef ALG_OP_SSGEN
#define ALG_OP_SSGEN 5
#endif
/* remove once in socket.h */
#ifndef AF_ALG
#define AF_ALG 38
#endif
#ifndef SOL_ALG
#define SOL_ALG 279
#endif
/* make sure that is equal to include/crypto/if_alg.h */
#ifndef ALG_MAX_PAGES
#define ALG_MAX_PAGES 16
#endif
/************************************************************
* Declarations for opaque data structures
************************************************************/
/* Boolean variable */
enum { false, true };
typedef _Bool bool;
enum kcapi_cipher_type {
KCAPI_CIPHER_SKCIPHER,
KCAPI_CIPHER_AEAD,
KCAPI_CIPHER_KDF,
KCAPI_CIPHER_RNG,
KCAPI_CIPHER_MD,
KCAPI_CIPHER_KPP,
KCAPI_CIPHER_AKCIPHER,
};
/**
* Information obtained for different ciphers during handle init time
* using the NETLINK_CRYPTO interface.
* @blocksize block size of cipher (hash, symmetric, AEAD)
* @ivsize size of IV of cipher (symmetric, AEAD)
* @hash_digestsize size of message digest (hash)
* @blk_min_keysize minimum key size (symmetric)
* @blk_max_keysize maximum key size (symmetric)
* @aead_maxauthsize maximum authentication tag size (AEAD)
* @rng_seedsize seed size (RNG)
*/
struct kcapi_cipher_info {
enum kcapi_cipher_type cipher_type;
/* generic */
uint32_t blocksize;
uint32_t ivsize;
/* hash */
uint32_t hash_digestsize;
/* blkcipher */
uint32_t blk_min_keysize;
uint32_t blk_max_keysize;
/* aead */
uint32_t aead_maxauthsize;
/* rng */
uint32_t rng_seedsize;
};
/**
* Common data required for symmetric and AEAD ciphers
* @iv: IV with length of kcapi_cipher_info->ivsize - input
*/
struct kcapi_cipher_data {
const uint8_t *iv;
};
/**
* AEAD data
* @datalen: Length of plaintext / ciphertext data - input
* @data: Pointer to plaintext / ciphertext data - input / output (the length is
* calculated with: kcapi_skcipher_data->inlen -
* kcapi_aead_data->taglen - kcapi_aead_data->assoclen)
* @assoclen: Length of associated data - input
* @assoc: Pointer to associated data - input
* @taglen: Length of authentication tag - input
* @tag: Authentication tag - input for decryption, output for encryption
* @retlen: internal data -- number plaintext / ciphertext bytes returned by
* the read system call
*/
struct kcapi_aead_data {
size_t datalen;
size_t assoclen;
size_t taglen;
uint8_t *data;
uint8_t *assoc;
uint8_t *tag;
};
/*
* This value sets the maximum number of concurrent AIO operations we support.
* This value can be changed as needed. However, note that the memory
* consumption of one cipher handle increases proportionally to this value. This
* means that during the _init API call processing, memory corresponding with
* this number must be allocated regardless whether it is used later on or not.
*
* If the caller supplies more IOVECs to be processed in parallel than this
* value, the libkcapi code below segments the the provided input data
* into IOVEC chunks of KCAPI_AIO_CONCURRENT size. Thus, the calling user
* will not see any difference when this value changes other than the
* performance impact during _init (the larger the value, the slower the
* _init processing) and later on during the cipher operations (the larger
* the value, the more parallel cipher operations are supported).
*/
#define KCAPI_AIO_CONCURRENT 64
/**
* AIO related data structure to hold all information for AIO
* @skcipher_aio_disable: AIO support for symmetric ciphers not present
* @efd: event file descriptor
* @aio_ctx: AIO context to use for AIO syscalls
* @iocb_ret: return code of each iocb request - set to AIO_OUTSTANDING until
* a return code is obtained
* @cio: Active concurrent IOCBs
*/
#define AIO_OUTSTANDING ((__s64)-(1<<13))
struct kcapi_aio {
bool disable;
int efd;
aio_context_t aio_ctx;
__s64 *iocb_ret;
struct iocb *cio;
struct iocb **ciopp;
};
struct kcapi_flags {
/*
* A flag to distinguish the new AEAD interface introduced with 4.9.0 to
* only require a tag if it is required as input or output.
*
* Also, kernels before 4.9.0 misbehave when no data is sent for hashing.
*/
bool ge_v4_9;
/* AF_ALG interfaces changed to process more pages concurrently. */
uint32_t alg_max_pages;
};
struct kcapi_sys {
unsigned long kernel_maj, kernel_minor, kernel_patchlevel;
};
/**
* Kernel crypto API TFM representation - The entries are static after
* initialization.
* @tfmfd: Socket descriptor for AF_ALG
* @sysinfo: System information
* @info: properties of ciphers
* @refcnt: reference counter of data structure
*/
struct kcapi_handle_tfm {
int tfmfd;
struct kcapi_sys sysinfo;
struct kcapi_cipher_info info;
atomic_t refcnt;
};
/**
* Cipher handle
* @tfm: kernel crypto API TFM
* @opfd: FD to open kernel crypto API TFM
* @pipes: vmplice/splice pipe pair
* @pagesize: Page size of the system
* @pipesize: Maximum amount of data that the pipe can handle
* @processed_sg: number of scatter/gather entries sent to the kernel
* @ciper: Common data for all ciphers
* @aead: AEAD cipher specific data
* @aio: AIO information
*/
struct kcapi_handle {
struct kcapi_handle_tfm *tfm;
int pipes[2];
int opfd;
unsigned int pagesize;
unsigned int pipesize;
size_t processed_sg;
struct kcapi_cipher_data cipher;
struct kcapi_aead_data aead;
struct kcapi_aio aio;
struct kcapi_flags flags;
};
/************************************************************
* Declarations for internal functions
************************************************************/
extern enum kcapi_verbosity kcapi_verbosity_level;
void kcapi_dolog(enum kcapi_verbosity severity, const char *fmt, ...);
static inline int *_kcapi_get_opfd(struct kcapi_handle *handle)
{
return &handle->opfd;
}
ssize_t _kcapi_common_send_meta(struct kcapi_handle *handle,
struct iovec *iov, size_t iovlen,
uint32_t enc, uint32_t flags);
ssize_t _kcapi_common_vmsplice_iov(struct kcapi_handle *handle,
struct iovec *iov, size_t iovlen,
uint32_t flags);
ssize_t _kcapi_common_send_data(struct kcapi_handle *handle,
struct iovec *iov, size_t iovlen,
uint32_t flags);
ssize_t _kcapi_common_recv_data(struct kcapi_handle *handle,
struct iovec *iov, size_t iovlen);
ssize_t _kcapi_common_read_data(struct kcapi_handle *handle,
uint8_t *out, size_t outlen);
int _kcapi_common_accept(struct kcapi_handle *handle);
int _kcapi_common_close(struct kcapi_handle *handle);
ssize_t _kcapi_common_vmsplice_chunk(struct kcapi_handle *handle,
const uint8_t *in, size_t inlen,
uint32_t flags);
int _kcapi_handle_init(struct kcapi_handle **caller, const char *type,
const char *ciphername, uint32_t flags);
void _kcapi_handle_destroy(struct kcapi_handle *handle);
int _kcapi_common_setkey(struct kcapi_handle *handle, const uint8_t *key,
uint32_t keylen);
int _kcapi_common_setentropy(struct kcapi_handle *handle, const uint8_t *ent,
uint32_t entlen);
ssize_t _kcapi_cipher_crypt(struct kcapi_handle *handle, const uint8_t *in,
size_t inlen, uint8_t *out, size_t outlen,
int access, unsigned int enc);
ssize_t _kcapi_cipher_crypt_chunk(struct kcapi_handle *handle,
const uint8_t *in, size_t inlen,
uint8_t *out, size_t outlen,
int access, unsigned int enc);
ssize_t _kcapi_cipher_crypt_aio(struct kcapi_handle *handle,
struct iovec *iniov, struct iovec *outiov,
size_t iovlen, int access, unsigned int enc);
int _kcapi_aio_send_iov(struct kcapi_handle *handle, struct iovec *iov,
size_t iovlen, int access, unsigned int enc);
int _kcapi_aio_read_iov(struct kcapi_handle *handle,
struct iovec *iov, size_t iovlen);
int32_t _kcapi_aio_read_all(struct kcapi_handle *handle, size_t toread,
struct timespec *timeout);
/************************************************************
* Declarations for system calls
************************************************************/
static inline int io_setup(unsigned n, aio_context_t *ctx)
{
return (int)syscall(__NR_io_setup, n, ctx);
}
static inline int io_destroy(aio_context_t ctx)
{
return (int)syscall(__NR_io_destroy, ctx);
}
static inline int io_submit(aio_context_t ctx, long n, struct iocb **iocb)
{
return (int)syscall(__NR_io_submit, ctx, n, iocb);
}
static inline int io_getevents(__attribute__((unused)) aio_context_t ctx,
__attribute__((unused)) long min,
__attribute__((unused)) long max,
__attribute__((unused)) struct io_event *events,
__attribute__((unused)) struct timespec *timeout)
{
#ifdef __NR_io_getevents
return (int)syscall(__NR_io_getevents, ctx, min, max, events, timeout);
#else
return -ENOSYS;
#endif
}
/************************************************************
* Auxiliary macros
************************************************************/
#if __GNUC__ >= 10
# define IMPL_SYMVER(name, version) \
__attribute__((__symver__("kcapi_" #name "@@LIBKCAPI_" version)))
# define ORIG_SYMVER(name, version) \
__attribute__((__symver__("kcapi_" #name "@LIBKCAPI_" version)))
#else
# define IMPL_SYMVER(name, version) \
__asm__(".symver impl_" #name ",kcapi_" #name "@@LIBKCAPI_" version);
# define ORIG_SYMVER(name, version) \
__asm__(".symver orig_" #name ",kcapi_" #name "@LIBKCAPI_" version);
#endif
#ifdef __cplusplus
}
#endif
#endif /* INTERNAL_H */
|