mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-26 13:44:15 +08:00
ubifs: authentication: Authenticate super block node
This adds a HMAC covering the super block node and adds the logic that decides if a filesystem shall be mounted unauthenticated or authenticated. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Richard Weinberger <richard@nod.at>
This commit is contained in:
parent
b5b1f08369
commit
e158e02ff7
@ -517,6 +517,65 @@ static struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c)
|
||||
return sup;
|
||||
}
|
||||
|
||||
static int authenticate_sb_node(struct ubifs_info *c,
|
||||
const struct ubifs_sb_node *sup)
|
||||
{
|
||||
unsigned int sup_flags = le32_to_cpu(sup->flags);
|
||||
u8 hmac_wkm[UBIFS_HMAC_ARR_SZ];
|
||||
int authenticated = !!(sup_flags & UBIFS_FLG_AUTHENTICATION);
|
||||
int hash_algo;
|
||||
int err;
|
||||
|
||||
if (c->authenticated && !authenticated) {
|
||||
ubifs_err(c, "authenticated FS forced, but found FS without authentication");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!c->authenticated && authenticated) {
|
||||
ubifs_err(c, "authenticated FS found, but no key given");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ubifs_msg(c, "Mounting in %sauthenticated mode",
|
||||
c->authenticated ? "" : "un");
|
||||
|
||||
if (!c->authenticated)
|
||||
return 0;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_UBIFS_FS_AUTHENTICATION))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
hash_algo = le16_to_cpu(sup->hash_algo);
|
||||
if (hash_algo >= HASH_ALGO__LAST) {
|
||||
ubifs_err(c, "superblock uses unknown hash algo %d",
|
||||
hash_algo);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (strcmp(hash_algo_name[hash_algo], c->auth_hash_name)) {
|
||||
ubifs_err(c, "This filesystem uses %s for hashing,"
|
||||
" but %s is specified", hash_algo_name[hash_algo],
|
||||
c->auth_hash_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = ubifs_hmac_wkm(c, hmac_wkm);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (ubifs_check_hmac(c, hmac_wkm, sup->hmac_wkm)) {
|
||||
ubifs_err(c, "provided key does not fit");
|
||||
return -ENOKEY;
|
||||
}
|
||||
|
||||
err = ubifs_node_verify_hmac(c, sup, sizeof(*sup),
|
||||
offsetof(struct ubifs_sb_node, hmac));
|
||||
if (err)
|
||||
ubifs_err(c, "Failed to authenticate superblock: %d", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* ubifs_write_sb_node - write superblock node.
|
||||
* @c: UBIFS file-system description object
|
||||
@ -527,8 +586,13 @@ static struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c)
|
||||
int ubifs_write_sb_node(struct ubifs_info *c, struct ubifs_sb_node *sup)
|
||||
{
|
||||
int len = ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size);
|
||||
int err;
|
||||
|
||||
err = ubifs_prepare_node_hmac(c, sup, UBIFS_SB_NODE_SZ,
|
||||
offsetof(struct ubifs_sb_node, hmac), 1);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ubifs_prepare_node(c, sup, UBIFS_SB_NODE_SZ, 1);
|
||||
return ubifs_leb_change(c, UBIFS_SB_LNUM, sup, len);
|
||||
}
|
||||
|
||||
@ -642,6 +706,10 @@ int ubifs_read_superblock(struct ubifs_info *c)
|
||||
c->double_hash = !!(sup_flags & UBIFS_FLG_DOUBLE_HASH);
|
||||
c->encrypted = !!(sup_flags & UBIFS_FLG_ENCRYPTION);
|
||||
|
||||
err = authenticate_sb_node(c, sup);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
if ((sup_flags & ~UBIFS_FLG_MASK) != 0) {
|
||||
ubifs_err(c, "Unknown feature flags found: %#x",
|
||||
sup_flags & ~UBIFS_FLG_MASK);
|
||||
|
Loading…
Reference in New Issue
Block a user