File: internal.h

package info (click to toggle)
libkcapi 1.4.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 2,992 kB
  • sloc: ansic: 13,808; sh: 2,422; perl: 1,949; makefile: 287
file content (374 lines) | stat: -rw-r--r-- 11,230 bytes parent folder | download
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 */