@@ -22,7 +22,7 @@ static bool parse_hash_alg_option(const char *arg, u32 *alg_ptr)
{
char *end;
unsigned long n = strtoul(arg, &end, 10);
- const struct fsverity_hash_alg *alg;
+ uint16_t alg;
if (*alg_ptr != 0) {
error_msg("--hash-alg can only be specified once");
@@ -37,8 +37,8 @@ static bool parse_hash_alg_option(const char *arg, u32 *alg_ptr)
/* Specified by name? */
alg = libfsverity_find_hash_alg_by_name(arg);
- if (alg != NULL) {
- *alg_ptr = alg->hash_num;
+ if (alg) {
+ *alg_ptr = alg;
return true;
}
error_msg("unknown hash algorithm: '%s'", arg);
@@ -57,7 +57,6 @@ static int read_callback(void *opague, void *buf, size_t count)
int fsverity_cmd_sign(const struct fsverity_command *cmd,
int argc, char *argv[])
{
- const struct fsverity_hash_alg *hash_alg = NULL;
struct filedes file = { .fd = -1 };
u32 block_size = 0;
u8 *salt = NULL;
@@ -69,7 +68,10 @@ int fsverity_cmd_sign(const struct fsverity_command *cmd,
struct libfsverity_signature_params sig_params;
u64 file_size;
char digest_hex[FS_VERITY_MAX_DIGEST_SIZE * 2 + 1];
+ char *hash_name = NULL;
u8 *sig = NULL;
+ u16 alg_nr = 0;
+ int digest_size;
size_t sig_size;
int status;
int c;
@@ -77,12 +79,12 @@ int fsverity_cmd_sign(const struct fsverity_command *cmd,
while ((c = getopt_long(argc, argv, "", longopts, NULL)) != -1) {
switch (c) {
case OPT_HASH_ALG:
- if (hash_alg != NULL) {
+ if (alg_nr) {
error_msg("--hash-alg can only be specified once");
goto out_usage;
}
- hash_alg = libfsverity_find_hash_alg_by_name(optarg);
- if (hash_alg == NULL) {
+ alg_nr = libfsverity_find_hash_alg_by_name(optarg);
+ if (!alg_nr) {
error_msg("unknown hash algorithm: '%s'",
optarg);
fputs("Available hash algorithms: ", stderr);
@@ -124,8 +126,8 @@ int fsverity_cmd_sign(const struct fsverity_command *cmd,
if (argc != 2)
goto out_usage;
- if (hash_alg == NULL)
- hash_alg = libfsverity_find_hash_alg_by_num(FS_VERITY_HASH_ALG_DEFAULT);
+ if (!alg_nr)
+ alg_nr = FS_VERITY_HASH_ALG_DEFAULT;
if (block_size == 0)
block_size = get_default_block_size();
@@ -147,7 +149,7 @@ int fsverity_cmd_sign(const struct fsverity_command *cmd,
memset(¶ms, 0, sizeof(struct libfsverity_merkle_tree_params));
params.version = 1;
- params.hash_algorithm = hash_alg->hash_num;
+ params.hash_algorithm = alg_nr;
params.block_size = block_size;
params.salt_size = salt_size;
params.salt = salt;
@@ -158,6 +160,8 @@ int fsverity_cmd_sign(const struct fsverity_command *cmd,
filedes_close(&file);
+ digest_size = libfsverity_digest_size(alg_nr);
+
memset(&sig_params, 0, sizeof(struct libfsverity_signature_params));
sig_params.keyfile = keyfile;
sig_params.certfile = certfile;
@@ -169,9 +173,10 @@ int fsverity_cmd_sign(const struct fsverity_command *cmd,
if (!write_signature(argv[1], sig, sig_size))
goto out_err;
- bin2hex(digest->digest, hash_alg->digest_size, digest_hex);
- printf("Signed file '%s' (%s:%s)\n", argv[0], hash_alg->name,
- digest_hex);
+ hash_name = libfsverity_hash_name(alg_nr);
+ bin2hex(digest->digest, digest_size, digest_hex);
+ printf("Signed file '%s' (%s:%s)\n", argv[0], hash_name, digest_hex);
+ free(hash_name);
status = 0;
out:
free(salt);
@@ -137,17 +137,17 @@ const struct fsverity_hash_alg fsverity_hash_algs[] = {
},
};
-const struct fsverity_hash_alg *
-libfsverity_find_hash_alg_by_name(const char *name)
+uint16_t libfsverity_find_hash_alg_by_name(const char *name)
{
int i;
for (i = 0; i < ARRAY_SIZE(fsverity_hash_algs); i++) {
if (fsverity_hash_algs[i].name &&
- !strcmp(name, fsverity_hash_algs[i].name))
- return &fsverity_hash_algs[i];
+ !strcmp(name, fsverity_hash_algs[i].name)) {
+ return fsverity_hash_algs[i].hash_num;
+ }
}
- return NULL;
+ return 0;
}
const struct fsverity_hash_alg *
@@ -160,6 +160,31 @@ libfsverity_find_hash_alg_by_num(unsigned int num)
return NULL;
}
+int libfsverity_digest_size(uint16_t alg_nr)
+{
+ if (alg_nr < ARRAY_SIZE(fsverity_hash_algs) &&
+ fsverity_hash_algs[alg_nr].name)
+ return fsverity_hash_algs[alg_nr].digest_size;
+
+ return -1;
+}
+
+char *libfsverity_hash_name(uint16_t alg_nr)
+{
+ int namelen;
+ char *hash_name = NULL;
+
+ if (alg_nr < ARRAY_SIZE(fsverity_hash_algs) &&
+ fsverity_hash_algs[alg_nr].name) {
+ namelen = strlen(fsverity_hash_algs[alg_nr].name);
+ hash_name = malloc(namelen + 1);
+ if (hash_name)
+ strcpy(hash_name, fsverity_hash_algs[alg_nr].name);
+ }
+
+ return hash_name;
+}
+
/* ->init(), ->update(), and ->final() all in one step */
void hash_full(struct hash_ctx *ctx, const void *data, size_t size,
uint8_t *digest)
@@ -58,7 +58,7 @@ struct libfsverity_signature_params {
struct fsverity_hash_alg {
const char *name;
- unsigned int digest_size;
+ int digest_size;
unsigned int block_size;
uint16_t hash_num;
struct hash_ctx *(*create_ctx)(const struct fsverity_hash_alg *alg);
@@ -108,11 +108,9 @@ libfsverity_sign_digest(const struct libfsverity_digest *digest,
* @name: Pointer to name of hash algorithm
*
* Returns:
- * struct fsverity_hash_alg success
- * NULL on error
+ * uint16_t containing hash algorithm number, zero on error.
*/
-const struct fsverity_hash_alg *
-libfsverity_find_hash_alg_by_name(const char *name);
+uint16_t libfsverity_find_hash_alg_by_name(const char *name);
/*
* libfsverity_find_hash_alg_by_num - Find hash algorithm by number
@@ -125,4 +123,24 @@ libfsverity_find_hash_alg_by_name(const char *name);
const struct fsverity_hash_alg *
libfsverity_find_hash_alg_by_num(unsigned int num);
+/*
+ * libfsverity_digest_size - Return size of digest for a given algorithm
+ * @alg_nr: Valid hash algorithm number
+ *
+ * Returns:
+ * int containing size of digest, -1 on error.
+ */
+int libfsverity_digest_size(uint16_t alg_nr);
+
+/*
+ * libfsverity_find_hash_name - Find name of hash algorithm by number
+ * @name: Number of hash algorithm
+ *
+ * Returns:
+ * New allocated string containing name of algorithm.
+ * String must be freed by caller.
+ * NULL on error
+ */
+char *libfsverity_hash_name(uint16_t num);
+
#endif