1 // SPDX-License-Identifier: MIT
2 /*
3 * The 'fsverity enable' command
4 *
5 * Copyright 2018 Google LLC
6 *
7 * Use of this source code is governed by an MIT-style
8 * license that can be found in the LICENSE file or at
9 * https://opensource.org/licenses/MIT.
10 */
11
12 #include "fsverity.h"
13
14 #include <fcntl.h>
15 #include <getopt.h>
16 #include <limits.h>
17
read_signature(const char * filename,u8 ** sig_ret,u32 * sig_size_ret)18 static bool read_signature(const char *filename, u8 **sig_ret,
19 u32 *sig_size_ret)
20 {
21 struct filedes file = { .fd = -1 };
22 u64 file_size;
23 u8 *sig = NULL;
24 bool ok = false;
25
26 if (!open_file(&file, filename, O_RDONLY, 0))
27 goto out;
28 if (!get_file_size(&file, &file_size))
29 goto out;
30 if (file_size <= 0) {
31 error_msg("signature file '%s' is empty", filename);
32 goto out;
33 }
34 if (file_size > 1000000) {
35 error_msg("signature file '%s' is too large", filename);
36 goto out;
37 }
38 sig = xmalloc(file_size);
39 if (!full_read(&file, sig, file_size))
40 goto out;
41 *sig_ret = sig;
42 *sig_size_ret = file_size;
43 sig = NULL;
44 ok = true;
45 out:
46 filedes_close(&file);
47 free(sig);
48 return ok;
49 }
50
51 static const struct option longopts[] = {
52 {"hash-alg", required_argument, NULL, OPT_HASH_ALG},
53 {"block-size", required_argument, NULL, OPT_BLOCK_SIZE},
54 {"salt", required_argument, NULL, OPT_SALT},
55 {"signature", required_argument, NULL, OPT_SIGNATURE},
56 {NULL, 0, NULL, 0}
57 };
58
59 /* Enable fs-verity on a file. */
fsverity_cmd_enable(const struct fsverity_command * cmd,int argc,char * argv[])60 int fsverity_cmd_enable(const struct fsverity_command *cmd,
61 int argc, char *argv[])
62 {
63 struct libfsverity_merkle_tree_params tree_params = { .version = 1 };
64 u8 *sig = NULL;
65 u32 sig_size = 0;
66 struct filedes file;
67 int status;
68 int c;
69
70 while ((c = getopt_long(argc, argv, "", longopts, NULL)) != -1) {
71 switch (c) {
72 case OPT_HASH_ALG:
73 case OPT_BLOCK_SIZE:
74 case OPT_SALT:
75 if (!parse_tree_param(c, optarg, &tree_params))
76 goto out_usage;
77 break;
78 case OPT_SIGNATURE:
79 if (sig != NULL) {
80 error_msg("--signature can only be specified once");
81 goto out_usage;
82 }
83 if (!read_signature(optarg, &sig, &sig_size))
84 goto out_err;
85 break;
86 default:
87 goto out_usage;
88 }
89 }
90
91 argv += optind;
92 argc -= optind;
93
94 if (argc != 1)
95 goto out_usage;
96
97 if (!open_file(&file, argv[0], O_RDONLY, 0))
98 goto out_err;
99
100 if (libfsverity_enable_with_sig(file.fd, &tree_params, sig, sig_size)) {
101 error_msg_errno("FS_IOC_ENABLE_VERITY failed on '%s'",
102 file.name);
103 filedes_close(&file);
104 goto out_err;
105 }
106 if (!filedes_close(&file))
107 goto out_err;
108
109 status = 0;
110 out:
111 destroy_tree_params(&tree_params);
112 free(sig);
113 return status;
114
115 out_err:
116 status = 1;
117 goto out;
118
119 out_usage:
120 usage(cmd, stderr);
121 status = 2;
122 goto out;
123 }
124