mirror of
https://github.com/kdave/btrfs-progs
synced 2025-01-02 19:52:02 +00:00
btrfs-progs: Add HMAC(SHA256) support
Add support for authenticated file systems using HMAC(SHA256) as checksumming algorithm. Example: mkfs.btrfs --csum hmac-sha256 --auth-key 0123456789 -f test.img Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
bbf56a44a4
commit
067454f955
@ -319,6 +319,7 @@ static bool is_valid_csum_type(u16 csum_type)
|
||||
case BTRFS_CSUM_TYPE_XXHASH:
|
||||
case BTRFS_CSUM_TYPE_SHA256:
|
||||
case BTRFS_CSUM_TYPE_BLAKE2:
|
||||
case BTRFS_CSUM_TYPE_HMAC_SHA256:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@ -352,7 +353,9 @@ static void dump_superblock(struct btrfs_super_block *sb, int full)
|
||||
printf("csum\t\t\t0x");
|
||||
for (i = 0, p = sb->csum; i < csum_size; i++)
|
||||
printf("%02x", p[i]);
|
||||
if (!is_valid_csum_type(csum_type))
|
||||
if (csum_type == BTRFS_CSUM_TYPE_HMAC_SHA256)
|
||||
printf(" [NO KEY FOR HMAC]");
|
||||
else if (!is_valid_csum_type(csum_type))
|
||||
printf(" [UNKNOWN CSUM TYPE OR SIZE]");
|
||||
else if (check_csum_sblock(sb, csum_size, csum_type))
|
||||
printf(" [match]");
|
||||
|
@ -774,6 +774,9 @@ enum btrfs_csum_type parse_csum_type(const char *s)
|
||||
} else if (strcasecmp(s, "blake2b") == 0 ||
|
||||
strcasecmp(s, "blake2") == 0) {
|
||||
return BTRFS_CSUM_TYPE_BLAKE2;
|
||||
} else if (strcasecmp(s, "hmac-sha256") == 0 ||
|
||||
strcasecmp(s, "hmac(sha256)") == 0) {
|
||||
return BTRFS_CSUM_TYPE_HMAC_SHA256;
|
||||
} else {
|
||||
error("unknown csum type %s", s);
|
||||
exit(1);
|
||||
|
@ -295,7 +295,6 @@ AC_SUBST([LZO2_LIBS])
|
||||
AC_SUBST([LZO2_LIBS_STATIC])
|
||||
AC_SUBST([LZO2_CFLAGS])
|
||||
|
||||
|
||||
dnl library stuff
|
||||
AC_SUBST([LIBBTRFS_MAJOR])
|
||||
AC_SUBST([LIBBTRFS_MINOR])
|
||||
|
@ -1,3 +1,7 @@
|
||||
#include <gcrypt.h>
|
||||
|
||||
#include "ctree.h"
|
||||
|
||||
#include "crypto/hash.h"
|
||||
#include "crypto/crc32c.h"
|
||||
#include "crypto/xxhash.h"
|
||||
@ -72,12 +76,25 @@ int hash_blake2b(const u8 *buf, size_t len, u8 *out)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hash_hmac_sha256(struct btrfs_fs_info *fs_info, const u8 *buf,
|
||||
size_t length, u8 *out)
|
||||
{
|
||||
gcry_mac_hd_t mac;
|
||||
gcry_mac_open(&mac, GCRY_MAC_HMAC_SHA256, 0, NULL);
|
||||
gcry_mac_setkey(mac, fs_info->auth_key, strlen(fs_info->auth_key));
|
||||
gcry_mac_write(mac, buf, length);
|
||||
gcry_mac_read(mac, out, &length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if CRYPTOPROVIDER_LIBSODIUM == 1
|
||||
|
||||
#include <sodium/crypto_hash_sha256.h>
|
||||
#include <sodium/crypto_generichash_blake2b.h>
|
||||
#include <sodium/crypto_auth_hmacsha256.h>
|
||||
|
||||
int hash_sha256(const u8 *buf, size_t len, u8 *out)
|
||||
{
|
||||
@ -90,4 +107,17 @@ int hash_blake2b(const u8 *buf, size_t len, u8 *out)
|
||||
NULL, 0);
|
||||
}
|
||||
|
||||
int hash_hmac_sha256(struct btrfs_fs_info *fs_info, const u8 *buf,
|
||||
size_t length, u8 *out)
|
||||
{
|
||||
crypto_auth_hmacsha256_state state;
|
||||
|
||||
crypto_auth_hmacsha256_init(&state, (unsigned char *)fs_info->auth_key,
|
||||
strlen(fs_info->auth_key));
|
||||
crypto_auth_hmacsha256_update(&state, buf, length);
|
||||
crypto_auth_hmacsha256_final(&state, out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -9,5 +9,7 @@ int hash_crc32c(const u8 *buf, size_t length, u8 *out);
|
||||
int hash_xxhash(const u8 *buf, size_t length, u8 *out);
|
||||
int hash_sha256(const u8 *buf, size_t length, u8 *out);
|
||||
int hash_blake2b(const u8 *buf, size_t length, u8 *out);
|
||||
int hash_hmac_sha256(struct btrfs_fs_info *fs_info, const u8 *buf,
|
||||
size_t length, u8 *out);
|
||||
|
||||
#endif
|
||||
|
1
ctree.c
1
ctree.c
@ -47,6 +47,7 @@ static const struct btrfs_csum {
|
||||
[BTRFS_CSUM_TYPE_XXHASH] = { 8, "xxhash64" },
|
||||
[BTRFS_CSUM_TYPE_SHA256] = { 32, "sha256" },
|
||||
[BTRFS_CSUM_TYPE_BLAKE2] = { 32, "blake2" },
|
||||
[BTRFS_CSUM_TYPE_HMAC_SHA256] = { 32, "hmac-sha256" },
|
||||
};
|
||||
|
||||
u16 btrfs_super_csum_size(const struct btrfs_super_block *sb)
|
||||
|
3
ctree.h
3
ctree.h
@ -172,6 +172,7 @@ enum btrfs_csum_type {
|
||||
BTRFS_CSUM_TYPE_XXHASH = 1,
|
||||
BTRFS_CSUM_TYPE_SHA256 = 2,
|
||||
BTRFS_CSUM_TYPE_BLAKE2 = 3,
|
||||
BTRFS_CSUM_TYPE_HMAC_SHA256 = 4,
|
||||
};
|
||||
|
||||
#define BTRFS_EMPTY_DIR_SIZE 0
|
||||
@ -1213,6 +1214,8 @@ struct btrfs_fs_info {
|
||||
u32 nodesize;
|
||||
u32 sectorsize;
|
||||
u32 stripesize;
|
||||
|
||||
char *auth_key;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -153,6 +153,10 @@ int btrfs_csum_data(struct btrfs_fs_info *fs_info, u16 csum_type,
|
||||
return hash_sha256(data, len, out);
|
||||
case BTRFS_CSUM_TYPE_BLAKE2:
|
||||
return hash_blake2b(data, len, out);
|
||||
case BTRFS_CSUM_TYPE_HMAC_SHA256:
|
||||
if (!fs_info || !fs_info->auth_key)
|
||||
return 0;
|
||||
return hash_hmac_sha256(fs_info, data, len, out);
|
||||
default:
|
||||
fprintf(stderr, "ERROR: unknown csum type: %d\n", csum_type);
|
||||
ASSERT(0);
|
||||
@ -837,6 +841,7 @@ struct btrfs_fs_info *btrfs_new_fs_info(int writable, u64 sb_bytenr,
|
||||
fs_info->data_alloc_profile = (u64)-1;
|
||||
fs_info->metadata_alloc_profile = (u64)-1;
|
||||
fs_info->system_alloc_profile = fs_info->metadata_alloc_profile;
|
||||
fs_info->auth_key = auth_key;
|
||||
return fs_info;
|
||||
free_all:
|
||||
btrfs_free_fs_info(fs_info);
|
||||
@ -1418,7 +1423,7 @@ int btrfs_check_super(struct btrfs_super_block *sb, unsigned sbflags)
|
||||
btrfs_csum_data(NULL, csum_type, (u8 *)sb + BTRFS_CSUM_SIZE,
|
||||
result, BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
|
||||
|
||||
if (memcmp(result, sb->csum, csum_size)) {
|
||||
if (memcmp(result, sb->csum, csum_size) && csum_type != BTRFS_CSUM_TYPE_HMAC_SHA256) {
|
||||
error("superblock checksum mismatch");
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -160,6 +160,13 @@ int make_btrfs(int fd, struct btrfs_mkfs_config *cfg)
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
buf->fs_info = calloc(1, sizeof(struct btrfs_fs_info));
|
||||
if (!buf->fs_info) {
|
||||
free(buf);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
first_free = BTRFS_SUPER_INFO_OFFSET + cfg->sectorsize * 2 - 1;
|
||||
first_free &= ~((u64)cfg->sectorsize - 1);
|
||||
|
||||
@ -224,6 +231,8 @@ int make_btrfs(int fd, struct btrfs_mkfs_config *cfg)
|
||||
btrfs_header_chunk_tree_uuid(buf),
|
||||
BTRFS_UUID_SIZE);
|
||||
|
||||
buf->fs_info->auth_key = cfg->auth_key;
|
||||
|
||||
ret = btrfs_create_tree_root(fd, cfg, buf);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
@ -474,6 +483,7 @@ int make_btrfs(int fd, struct btrfs_mkfs_config *cfg)
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
free(buf->fs_info);
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
@ -65,6 +65,9 @@ struct btrfs_mkfs_config {
|
||||
|
||||
/* Superblock offset after make_btrfs */
|
||||
u64 super_bytenr;
|
||||
|
||||
/* authentication key */
|
||||
char *auth_key;
|
||||
};
|
||||
|
||||
int make_btrfs(int fd, struct btrfs_mkfs_config *cfg);
|
||||
|
22
mkfs/main.c
22
mkfs/main.c
@ -344,6 +344,7 @@ static void print_usage(int ret)
|
||||
printf(" features:\n");
|
||||
printf("\t--csum TYPE\n");
|
||||
printf("\t--checksum TYPE checksum algorithm to use (default: crc32c)\n");
|
||||
printf("\t--auth-key KEY authentication key to use for authenticated file-systems\n");
|
||||
printf("\t-n|--nodesize SIZE size of btree nodes\n");
|
||||
printf("\t-s|--sectorsize SIZE data block size (may not be mountable by current kernel)\n");
|
||||
printf("\t-O|--features LIST comma separated list of filesystem features (use '-O list-all' to list features)\n");
|
||||
@ -951,14 +952,21 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
|
||||
struct mkfs_allocation allocation = { 0 };
|
||||
struct btrfs_mkfs_config mkfs_cfg;
|
||||
enum btrfs_csum_type csum_type = BTRFS_CSUM_TYPE_CRC32;
|
||||
char *auth_key = NULL;
|
||||
|
||||
crc32c_optimization_init();
|
||||
|
||||
while(1) {
|
||||
int c;
|
||||
enum { GETOPT_VAL_SHRINK = 257, GETOPT_VAL_CHECKSUM };
|
||||
enum {
|
||||
GETOPT_VAL_SHRINK = 257,
|
||||
GETOPT_VAL_CHECKSUM,
|
||||
GETOPT_VAL_AUTHKEY,
|
||||
};
|
||||
static const struct option long_options[] = {
|
||||
{ "alloc-start", required_argument, NULL, 'A'},
|
||||
{ "auth-key", required_argument, NULL,
|
||||
GETOPT_VAL_AUTHKEY },
|
||||
{ "byte-count", required_argument, NULL, 'b' },
|
||||
{ "csum", required_argument, NULL,
|
||||
GETOPT_VAL_CHECKSUM },
|
||||
@ -1064,6 +1072,9 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
|
||||
case GETOPT_VAL_CHECKSUM:
|
||||
csum_type = parse_csum_type(optarg);
|
||||
break;
|
||||
case GETOPT_VAL_AUTHKEY:
|
||||
auth_key = strdup(optarg);
|
||||
break;
|
||||
case GETOPT_VAL_HELP:
|
||||
default:
|
||||
print_usage(c != GETOPT_VAL_HELP);
|
||||
@ -1091,6 +1102,12 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((auth_key && csum_type != BTRFS_CSUM_TYPE_HMAC_SHA256) ||
|
||||
(csum_type == BTRFS_CSUM_TYPE_HMAC_SHA256 && !auth_key)) {
|
||||
error("the option --auth-key must be used with --csum hmac(sha256)");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (*fs_uuid) {
|
||||
uuid_t dummy_uuid;
|
||||
|
||||
@ -1309,6 +1326,7 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
|
||||
mkfs_cfg.stripesize = stripesize;
|
||||
mkfs_cfg.features = features;
|
||||
mkfs_cfg.csum_type = csum_type;
|
||||
mkfs_cfg.auth_key = auth_key;
|
||||
|
||||
ret = make_btrfs(fd, &mkfs_cfg);
|
||||
if (ret) {
|
||||
@ -1525,6 +1543,7 @@ out:
|
||||
|
||||
btrfs_close_all_devices();
|
||||
free(label);
|
||||
free(auth_key);
|
||||
|
||||
return !!ret;
|
||||
error:
|
||||
@ -1532,6 +1551,7 @@ error:
|
||||
close(fd);
|
||||
|
||||
free(label);
|
||||
free(auth_key);
|
||||
exit(1);
|
||||
success:
|
||||
exit(0);
|
||||
|
Loading…
Reference in New Issue
Block a user