• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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