xref: /aosp_15_r20/external/fsverity-utils/programs/cmd_enable.c (revision b13c0e4024008a1f948ee8189745cb3371f4ac04)
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