[go: up one dir, main page]

File: pv_utils.h

package info (click to toggle)
s390-tools 2.35.0-1
  • links: PTS
  • area: main
  • in suites: trixie
  • size: 12,220 kB
  • sloc: ansic: 184,236; sh: 12,152; cpp: 4,954; makefile: 2,763; perl: 2,519; asm: 1,085; python: 697; xml: 29
file content (348 lines) | stat: -rw-r--r-- 11,328 bytes parent folder | download | duplicates (2)
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
/*
 * zgetdump - Tool for copying and converting System z dumps
 *
 * Utilities to decrypt secure execution guest dumps.
 *
 * Copyright IBM Corp. 2022
 *
 * s390-tools is free software; you can redistribute it and/or modify
 * it under the terms of the MIT license. See LICENSE for details.
 */

#ifndef PV_UTILS_H
#define PV_UTILS_H

#include <stdbool.h>

#include <openssl/evp.h>

#include "lib/util_log.h"
#include "libpv/crypto.h"

#include "df_elf.h"
#include "dfi.h"
#include "pv_defs.h"
#include <stdint.h>

#define PV_INVAL_PAGE_STATE 0UL
#define PV_ENCRYPTED_PAGE   (1UL << 0)
#define PV_SHARED_PAGE	    (1UL << 1)
#define PV_ZERO_PAGE	    (1UL << 2)
#define PV_MAPPED_PAGE	    (1UL << 3)

#define FUNC_NAME_FLAT_STRUCT_CLEANSE_FREE(type) type##_flat_struct_cleanse_free
#define DEFINE_FLAT_STRUCT_CLEANSE_FREE(type, free_func)                                           \
	static void FUNC_NAME_FLAT_STRUCT_CLEANSE_FREE(type)(type * obj)                           \
	{                                                                                          \
		if (!obj)                                                                          \
			return;                                                                    \
		OPENSSL_cleanse(obj, sizeof(type));                                                \
		free_func(obj);                                                                    \
	}

/* The typedef is required to be able to define a autoptr cleanup
 * function using glib2.
 */
typedef struct dfi_cpu dfi_cpu_t;

DEFINE_FLAT_STRUCT_CLEANSE_FREE(dfi_cpu_t, dfi_cpu_free)
DEFINE_FLAT_STRUCT_CLEANSE_FREE(pv_dump_completion_data_v1_t, g_free)
DEFINE_FLAT_STRUCT_CLEANSE_FREE(pv_dump_completion_confidential_area_v1_t, g_free)

WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(dfi_cpu_t, FUNC_NAME_FLAT_STRUCT_CLEANSE_FREE(dfi_cpu_t))
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(
	pv_dump_completion_data_v1_t,
	FUNC_NAME_FLAT_STRUCT_CLEANSE_FREE(pv_dump_completion_data_v1_t))
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(
	pv_dump_completion_confidential_area_v1_t,
	FUNC_NAME_FLAT_STRUCT_CLEANSE_FREE(pv_dump_completion_confidential_area_v1_t))

typedef struct _pv_crypto_ctx pv_crypto_ctx_t;
typedef struct _storage_state_mmap storage_state_mmap_t;
struct _pv_elf_ctx {
	BIO *output;
	u64 elf_load_off;
	pv_crypto_ctx_t *pv_ctx;
	storage_state_mmap_t *storage_state_data;
};
typedef struct _pv_elf_ctx pv_elf_ctx_t;

void pv_dump_completion_free(pv_dump_completion_t *cpl);
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(pv_dump_completion_t, pv_dump_completion_free)

/**
 * pv_derive_dump_key_v1:
 * @cpl_data: v1 dump completion data
 * @cck: Customer communication key
 * @error: return location for a #GError
 *
 * Derives an 32 byte AES-256-GCM key using the key derivation function HDKF
 * together with the customer communication key (CCK) @cck as input keying
 * material, and the seed from the completion configuration dump @cpl_data as salt.
 *
 * Returns: 32 byte AES-256-GCM key on success, %NULL if an error occurred
 */
GBytes *pv_derive_dump_key_v1(const pv_dump_completion_data_v1_t *cpl_data, GBytes *cck,
			      GError **error);

/**
 * pv_decrypt_dump_completion_v1:
 * @cpl_data: v1 dump completion data
 * @dump_key: Dump key
 * @error: return location for a #GError
 *
 * Decrypts and authenticates the completion configuration dump data @cpl_data
 * using the AES-256-GCM @dump_key.
 *
 * Returns: Decrypted confidential area of the completion configuration dump on success,
 *          %NULL if an error occurred
 */
pv_dump_completion_v1_t *pv_decrypt_dump_completion_v1(const pv_dump_completion_data_v1_t *cpl_data,
						       GBytes *dump_key, GError **error);

dfi_cpu_t *pv_decrypt_cpu_note_data(const unsigned int expected_version, GBytes *cpu_note,
				    GBytes *dump_key, GError **error);

/**
 * pv_decrypt_cpu_dump_area_v1:
 * @cpu_dump_area: a v1 CPU dump area
 * @dump_key: Dump key
 * @error: return location for a #GError
 *
 * Decrypts and authenticates a secure CPU dump using AES-256-GCM with specified
 * dump_key.
 *
 * Returns: Decrypted part of the CPU dump on success, %NULL if an error occurred
 */
GBytes *pv_decrypt_cpu_dump_area_v1(const pv_cpu_dump_v1_t *cpu_dump_area, GBytes *dump_key,
				    GError **error);

/**
 * pv_dfi_cpu_from_pv_cpu:
 * @pv_cpu: PV CPU data
 *
 * Convert PV CPU data to internal dfi_cpu struct.
 *
 * Returns: #dfi_cpu struct
 */
dfi_cpu_t *pv_dfi_cpu_from_pv_cpu(const pv_cpu_dump_confidential_area_v1_t *pv_cpu);

/**
 * pv_crypto_ctx_new:
 * @input: a #BIO input
 * @key: (array length=key_size): byte data of the key
 * @key_size: size of @key in bytes
 * @nonce: The PV tweak nonce
 * @mode: encrypt or decrypt mode
 * @error: return location for a #GError
 *
 * Create a PV crypto context using @input as the input, @key as the cipher key
 * and @nonce as the nonce for deriving the tweaks.
 *
 * Returns: a new #pv_crypto_ctx_t
 */
pv_crypto_ctx_t *pv_crypto_ctx_new(BIO *input, const unsigned char *key, size_t key_size,
				   const pv_tweak_nonce_t *nonce, enum PvCryptoMode mode,
				   GError **error);

/**
 * pv_crypto_ctx_free:
 * @ctx: a #pv_crypto_ctx_t
 *
 * Free all resources and the memory allocated for the #pv_crypto_ctx_t
 */
void pv_crypto_ctx_free(pv_crypto_ctx_t *ctx);

/**
 * pv_process_pglist:
 * @ctx: a #pv_crypto_ctx_t context
 * @output: Output
 * @tweaks_components: (array length=tweaks_len) (element-type pv_tweak_component_t): tweaks
 * components to be used for the decryption
 * @tweaks_components_len: the length of @tweaks and the length of the page list to be processed
 * @input_off: the file offset of the encrypted memory passed in @ctx to decrypt
 * @error: return location for a #GError
 *
 * Decrypts a page block (e.g. 256 pages).
 *
 * Returns: number of processed pages on success, -1 if an error occurred
 */
ssize_t pv_process_pglist(pv_crypto_ctx_t *ctx, BIO *output,
			  const pv_tweak_component_t *tweak_components, size_t tweak_components_len,
			  long input_off, GError **error);

/**
 * calculate_tweak:
 *
 * calculates the bitwise or of tweak component and nonce.
 */
void calculate_tweak(const pv_tweak_component_t *tweak, const pv_tweak_nonce_t *nonce,
		     pv_tweak_t *out);
/**
 * pv_read_page:
 * @output: Input
 * @output: Output
 *
 * Read one page data from @input and write it to @output.
 *
 * Returns: The number of bytes read for success, -1 if an error occurred
 */
int pv_read_page(BIO *input, BIO *output, GError **error);

/**
 * pv_page_state:
 *
 * Get the page state of the tweak component.
 */
unsigned long pv_page_state(const pv_tweak_component_t *comp);

/**
 * pv_get_tweak_components:
 * @storage_state_data: input data
 * @page_idx: Page index of the fist page
 * @page_cnt: number of tweak components that can be at least accessed
 *
 * get a pointer to the page states of the given pages.
 *
 * Returns: pointer to page states or NULL in case of an error
 *
 */
const pv_tweak_component_t *pv_get_tweak_components(storage_state_mmap_t *storage_state_data,
						    u64 page_idx, u64 page_cnt);

/**
 * pv_elf_ctx_new:
 * fd: file descriptor of elf file
 * @completion_confidential_decr:  content of ection pv_meta size must be
 * sizeof(pv_dump_completion_confidential_area_t)
 * @storage_state_data: mmap to pv_mem_meta
 * @load_offset: offset of LOAD segment in fd
 * @error: return value for GError
 *
 * creates a new elf context for processing the elf file
 *
 * Returns: new elf context or NULL in case of error
 */
pv_elf_ctx_t *
pv_elf_ctx_new(const int fd,
	       const pv_dump_completion_confidential_area_v1_t *completion_confidential_decr,
	       storage_state_mmap_t *storage_state_data, const u64 load_offset, GError **error);

/**
 * pv_info_free:
 * frees the elf context
 */
void pv_elf_ctx_free(pv_elf_ctx_t *p);

/**
 * pv_is_pv_elf:
 * @shdrs: list of section headers
 * @shnum: size of shdrs list
 * @shstrtab: content of shstrtab (section hdr string table)
 * @shstrtab_size: size of shstrtab
 *
 * Returns: true in case it is a PV ELF vmcore dump, false otherwise.
 */
bool pv_is_pv_elf(const Elf64_Shdr *shdrs, const unsigned int shnum, const char *shstrtab,
		  const size_t shstrtab_size);

/**
 * pv_process_section_data:
 *
 * Uses the ELF sections data to derive dump key, using the provided
 * customer-communication-key. It copies the decrypted completion
 * data into @completion_decr and mmaps storage state tweaks to storage
 * state data.
 *
 * The caller is responsible for cleanup and overwriting.
 *
 * Returns: 0 in case of success, -1 otherwise.
 */
int pv_process_section_data(const int fd, const size_t file_size, GBytes *completion_sec,
			    const u64 storage_state_offset, const size_t storage_state_size,
			    GBytes *cck, pv_dump_completion_t **completion_decr, GBytes **dump_key,
			    storage_state_mmap_t **storage_state_data, GError **error);

/**
 * pv_elf_read:
 *
 * elf_ctx: elf context
 * @start_addr: first address to read from
 * @dst: target
 * @size: num bytes to read
 * @error: return value for GError
 *
 * Read size bytes from start addr in elf_ctx and save it into dest.
 * Will decrypt pages if defined by page state.
 *
 * Returns: 0 in case of success, -1 otherwise.
 */
int pv_elf_read(const pv_elf_ctx_t *elf_ctx, const u64 start_addr, void *dst, const u64 size,
		GError **error);

/**
 * storage_state_mmap_new:
 * @fd: file descriptor for which to create the mapping
 * @file_size: file size in bytes
 * @offset: offset in fd to pv_mem_meta section
 * @size: size of mapping  (and pv_mem_meta section)
 * @error: return value for GError
 *
 * Returns: new storage_state_mmap context
 */
storage_state_mmap_t *storage_state_mmap_new(const int fd, const size_t file_size, const u64 offset,
					     const u64 size, GError **error);

/**
 * storage_state_ref:
 *
 * increase the reference counter by one.
 *
 * Returns: pointer to storage_state
 */
storage_state_mmap_t *storage_state_mmap_ref(storage_state_mmap_t *storage_state);

/**
 * storage_state_unref:
 *
 * Decreases the reference counter by one.
 * If the counter is now zero storage_state will be unmapped and freed.
 * If the munmap fails, an error will be logged.
 */
void storage_state_mmap_unref(storage_state_mmap_t *storage_state);

#define ZDUMP_PV_UTILS_ERROR g_quark_from_static_string("zdump-pv-utils")
typedef enum {
	ZDUMP_ERR_BIO,
	ZDUMP_ERR_BIO_FAIL,
	ZDUMP_ERR_BIO_KEY,
	ZDUMP_ERR_CORRUPTED_COMPL_DATA,
	ZDUMP_ERR_CORRUPTED_NOTE,
	ZDUMP_ERR_CRYPTO_CTX,
	ZDUMP_ERR_ELF_CTX,
	ZDUMP_ERR_ELF_CTX_BIO,
	ZDUMP_ERR_ELF_READ,
	ZDUMP_ERR_ELF_READ_END_ADDR_OVERFLOW,
	ZDUMP_ERR_MMAP,
	ZDUMP_ERR_PAGELIST_ELF_OFFSET_TOO_LARGE,
	ZDUMP_ERR_PAGE_END_ADDR_OVERFLOW,
	ZDUMP_ERR_PAGE_START_ADDR_OVERFLOW,
	ZDUMP_ERR_PGLIST_BIO,
	ZDUMP_ERR_PGLIST_INVAL,
	ZDUMP_ERR_PGLIST_INVAL_STATE,
	ZDUMP_ERR_PROC_SECT,
	ZDUMP_ERR_TWEAK,
	ZDUMP_ERR_UNSUPP_COMPL_VER,
	ZDUMP_ERR_UNSUPP_SEC_CPU_VER,
	ZDUMP_ERR_WRONG_AAD_SIZE,
	ZDUMP_ERR_WRONG_CCK_SIZE,
	ZDUMP_ERR_WRONG_CONFIDENTIAL_SIZE,
	ZDUMP_ERR_WRONG_NOTE_SIZE,
	ZDUMP_ERR_WRONG_TAG_SIZE,
} zdump_pv_utils_error_e;

WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(pv_crypto_ctx_t, pv_crypto_ctx_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(pv_elf_ctx_t, pv_elf_ctx_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(storage_state_mmap_t, storage_state_mmap_unref)

#endif /* PV_UTILS_H */