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