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