aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'tools/testing/selftests/filesystems/incfs/utils.c')
-rw-r--r--tools/testing/selftests/filesystems/incfs/utils.c377
1 files changed, 377 insertions, 0 deletions
diff --git a/tools/testing/selftests/filesystems/incfs/utils.c b/tools/testing/selftests/filesystems/incfs/utils.c
new file mode 100644
index 000000000000..08b8452ad0bc
--- /dev/null
+++ b/tools/testing/selftests/filesystems/incfs/utils.c
@@ -0,0 +1,377 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright 2018 Google LLC
4 */
5#include <stdio.h>
6#include <fcntl.h>
7#include <dirent.h>
8#include <sys/types.h>
9#include <sys/stat.h>
10#include <fcntl.h>
11#include <unistd.h>
12#include <sys/ioctl.h>
13#include <sys/mount.h>
14#include <errno.h>
15#include <string.h>
16#include <poll.h>
17#include <openssl/bio.h>
18#include <openssl/err.h>
19#include <openssl/pem.h>
20#include <openssl/pkcs7.h>
21#include <openssl/sha.h>
22#include <openssl/md5.h>
23
24#include "utils.h"
25
26int mount_fs(char *mount_dir, char *backing_dir, int read_timeout_ms)
27{
28 static const char fs_name[] = INCFS_NAME;
29 char mount_options[512];
30 int result;
31
32 snprintf(mount_options, ARRAY_SIZE(mount_options),
33 "read_timeout_ms=%u",
34 read_timeout_ms);
35
36 result = mount(backing_dir, mount_dir, fs_name, 0, mount_options);
37 if (result != 0)
38 perror("Error mounting fs.");
39 return result;
40}
41
42int mount_fs_opt(char *mount_dir, char *backing_dir, char *opt)
43{
44 static const char fs_name[] = INCFS_NAME;
45 int result;
46
47 result = mount(backing_dir, mount_dir, fs_name, 0, opt);
48 if (result != 0)
49 perror("Error mounting fs.");
50 return result;
51}
52
53int unlink_node(int fd, int parent_ino, char *filename)
54{
55 return 0;
56}
57
58
59static EVP_PKEY *deserialize_private_key(const char *pem_key)
60{
61 BIO *bio = NULL;
62 EVP_PKEY *pkey = NULL;
63 int len = strlen(pem_key);
64
65 bio = BIO_new_mem_buf(pem_key, len);
66 if (!bio)
67 return NULL;
68
69 pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
70 BIO_free(bio);
71 return pkey;
72}
73
74static X509 *deserialize_cert(const char *pem_cert)
75{
76 BIO *bio = NULL;
77 X509 *cert = NULL;
78 int len = strlen(pem_cert);
79
80 bio = BIO_new_mem_buf(pem_cert, len);
81 if (!bio)
82 return NULL;
83
84 cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
85 BIO_free(bio);
86 return cert;
87}
88
89bool sign_pkcs7(const void *data_to_sign, size_t data_size,
90 char *pkey_pem, char *cert_pem,
91 void **sig_ret, size_t *sig_size_ret)
92{
93 /*
94 * PKCS#7 signing flags:
95 *
96 * - PKCS7_BINARY signing binary data, so skip MIME translation
97 *
98 * - PKCS7_NOATTR omit extra authenticated attributes, such as
99 * SMIMECapabilities
100 *
101 * - PKCS7_PARTIAL PKCS7_sign() creates a handle only, then
102 * PKCS7_sign_add_signer() can add a signer later.
103 * This is necessary to change the message digest
104 * algorithm from the default of SHA-1. Requires
105 * OpenSSL 1.0.0 or later.
106 */
107 int pkcs7_flags = PKCS7_BINARY | PKCS7_NOATTR | PKCS7_PARTIAL;
108 void *sig;
109 size_t sig_size;
110 BIO *bio = NULL;
111 PKCS7 *p7 = NULL;
112 EVP_PKEY *pkey = NULL;
113 X509 *cert = NULL;
114 bool ok = false;
115
116 const EVP_MD *md = EVP_sha256();
117
118 pkey = deserialize_private_key(pkey_pem);
119 if (!pkey) {
120 printf("deserialize_private_key failed\n");
121 goto out;
122 }
123
124 cert = deserialize_cert(cert_pem);
125 if (!cert) {
126 printf("deserialize_cert failed\n");
127 goto out;
128 }
129
130 bio = BIO_new_mem_buf(data_to_sign, data_size);
131 if (!bio)
132 goto out;
133
134 p7 = PKCS7_sign(NULL, NULL, NULL, bio, pkcs7_flags);
135 if (!p7) {
136 printf("failed to initialize PKCS#7 signature object\n");
137 goto out;
138 }
139
140 if (!PKCS7_sign_add_signer(p7, cert, pkey, md, pkcs7_flags)) {
141 printf("failed to add signer to PKCS#7 signature object\n");
142 goto out;
143 }
144
145 if (PKCS7_final(p7, bio, pkcs7_flags) != 1) {
146 printf("failed to finalize PKCS#7 signature\n");
147 goto out;
148 }
149
150 BIO_free(bio);
151 bio = BIO_new(BIO_s_mem());
152 if (!bio) {
153 printf("out of memory\n");
154 goto out;
155 }
156
157 if (i2d_PKCS7_bio(bio, p7) != 1) {
158 printf("failed to DER-encode PKCS#7 signature object\n");
159 goto out;
160 }
161
162 sig_size = BIO_get_mem_data(bio, &sig);
163 *sig_ret = malloc(sig_size);
164 memcpy(*sig_ret, sig, sig_size);
165 *sig_size_ret = sig_size;
166 ok = true;
167out:
168 PKCS7_free(p7);
169 BIO_free(bio);
170 return ok;
171}
172
173int crypto_emit_file(int fd, char *dir, char *filename, incfs_uuid_t *id_out,
174 size_t size, const char *root_hash, char *sig, size_t sig_size,
175 char *add_data)
176{
177 int mode = __S_IFREG | 0555;
178 struct incfs_file_signature_info sig_info = {
179 .hash_tree_alg = root_hash
180 ? INCFS_HASH_TREE_SHA256
181 : 0,
182 .root_hash = ptr_to_u64(root_hash),
183 .additional_data = ptr_to_u64(add_data),
184 .additional_data_size = strlen(add_data),
185 .signature = ptr_to_u64(sig),
186 .signature_size = sig_size,
187 };
188
189 struct incfs_new_file_args args = {
190 .size = size,
191 .mode = mode,
192 .file_name = ptr_to_u64(filename),
193 .directory_path = ptr_to_u64(dir),
194 .signature_info = ptr_to_u64(&sig_info),
195 .file_attr = 0,
196 .file_attr_len = 0
197 };
198
199 md5(filename, strlen(filename), (char *)args.file_id.bytes);
200
201 if (ioctl(fd, INCFS_IOC_CREATE_FILE, &args) != 0)
202 return -errno;
203
204 *id_out = args.file_id;
205 return 0;
206}
207
208
209int emit_file(int fd, char *dir, char *filename, incfs_uuid_t *id_out,
210 size_t size, char *attr)
211{
212 int mode = __S_IFREG | 0555;
213 struct incfs_file_signature_info sig_info = {
214 .hash_tree_alg = 0,
215 .root_hash = ptr_to_u64(NULL)
216 };
217 struct incfs_new_file_args args = {
218 .size = size,
219 .mode = mode,
220 .file_name = ptr_to_u64(filename),
221 .directory_path = ptr_to_u64(dir),
222 .signature_info = ptr_to_u64(&sig_info),
223 .file_attr = ptr_to_u64(attr),
224 .file_attr_len = attr ? strlen(attr) : 0
225 };
226
227 md5(filename, strlen(filename), (char *)args.file_id.bytes);
228
229 if (ioctl(fd, INCFS_IOC_CREATE_FILE, &args) != 0)
230 return -errno;
231
232 *id_out = args.file_id;
233 return 0;
234}
235
236int get_file_bmap(int cmd_fd, int ino, unsigned char *buf, int buf_size)
237{
238 return 0;
239}
240
241int get_file_signature(int fd, unsigned char *buf, int buf_size)
242{
243 struct incfs_get_file_sig_args args = {
244 .file_signature = ptr_to_u64(buf),
245 .file_signature_buf_size = buf_size
246 };
247
248 if (ioctl(fd, INCFS_IOC_READ_FILE_SIGNATURE, &args) == 0)
249 return args.file_signature_len_out;
250 return -errno;
251}
252
253loff_t get_file_size(char *name)
254{
255 struct stat st;
256
257 if (stat(name, &st) == 0)
258 return st.st_size;
259 return -ENOENT;
260}
261
262int open_commands_file(char *mount_dir)
263{
264 char cmd_file[255];
265 int cmd_fd;
266
267 snprintf(cmd_file, ARRAY_SIZE(cmd_file),
268 "%s/%s", mount_dir, INCFS_PENDING_READS_FILENAME);
269 cmd_fd = open(cmd_file, O_RDONLY);
270
271 if (cmd_fd < 0)
272 perror("Can't open commands file");
273 return cmd_fd;
274}
275
276int open_log_file(char *mount_dir)
277{
278 char cmd_file[255];
279 int cmd_fd;
280
281 snprintf(cmd_file, ARRAY_SIZE(cmd_file), "%s/.log", mount_dir);
282 cmd_fd = open(cmd_file, O_RDWR);
283 if (cmd_fd < 0)
284 perror("Can't open log file");
285 return cmd_fd;
286}
287
288int wait_for_pending_reads(int fd, int timeout_ms,
289 struct incfs_pending_read_info *prs, int prs_count)
290{
291 ssize_t read_res = 0;
292
293 if (timeout_ms > 0) {
294 int poll_res = 0;
295 struct pollfd pollfd = {
296 .fd = fd,
297 .events = POLLIN
298 };
299
300 poll_res = poll(&pollfd, 1, timeout_ms);
301 if (poll_res < 0)
302 return -errno;
303 if (poll_res == 0)
304 return 0;
305 if (!(pollfd.revents | POLLIN))
306 return 0;
307 }
308
309 read_res = read(fd, prs, prs_count * sizeof(*prs));
310 if (read_res < 0)
311 return -errno;
312
313 return read_res / sizeof(*prs);
314}
315
316char *concat_file_name(const char *dir, char *file)
317{
318 char full_name[FILENAME_MAX] = "";
319
320 if (snprintf(full_name, ARRAY_SIZE(full_name), "%s/%s", dir, file) < 0)
321 return NULL;
322 return strdup(full_name);
323}
324
325int delete_dir_tree(const char *dir_path)
326{
327 DIR *dir = NULL;
328 struct dirent *dp;
329 int result = 0;
330
331 dir = opendir(dir_path);
332 if (!dir) {
333 result = -errno;
334 goto out;
335 }
336
337 while ((dp = readdir(dir))) {
338 char *full_path;
339
340 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
341 continue;
342
343 full_path = concat_file_name(dir_path, dp->d_name);
344 if (dp->d_type == DT_DIR)
345 result = delete_dir_tree(full_path);
346 else
347 result = unlink(full_path);
348 free(full_path);
349 if (result)
350 goto out;
351 }
352
353out:
354 if (dir)
355 closedir(dir);
356 if (!result)
357 rmdir(dir_path);
358 return result;
359}
360
361void sha256(char *data, size_t dsize, char *hash)
362{
363 SHA256_CTX ctx;
364
365 SHA256_Init(&ctx);
366 SHA256_Update(&ctx, data, dsize);
367 SHA256_Final((unsigned char *)hash, &ctx);
368}
369
370void md5(char *data, size_t dsize, char *hash)
371{
372 MD5_CTX ctx;
373
374 MD5_Init(&ctx);
375 MD5_Update(&ctx, data, dsize);
376 MD5_Final((unsigned char *)hash, &ctx);
377}