Skip to content

Commit e158e02

Browse files
saschahauerrichardweinberger
authored andcommitted
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>
1 parent b5b1f08 commit e158e02

File tree

1 file changed

+69
-1
lines changed

1 file changed

+69
-1
lines changed

fs/ubifs/sb.c

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,65 @@ static struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c)
517517
return sup;
518518
}
519519

520+
static int authenticate_sb_node(struct ubifs_info *c,
521+
const struct ubifs_sb_node *sup)
522+
{
523+
unsigned int sup_flags = le32_to_cpu(sup->flags);
524+
u8 hmac_wkm[UBIFS_HMAC_ARR_SZ];
525+
int authenticated = !!(sup_flags & UBIFS_FLG_AUTHENTICATION);
526+
int hash_algo;
527+
int err;
528+
529+
if (c->authenticated && !authenticated) {
530+
ubifs_err(c, "authenticated FS forced, but found FS without authentication");
531+
return -EINVAL;
532+
}
533+
534+
if (!c->authenticated && authenticated) {
535+
ubifs_err(c, "authenticated FS found, but no key given");
536+
return -EINVAL;
537+
}
538+
539+
ubifs_msg(c, "Mounting in %sauthenticated mode",
540+
c->authenticated ? "" : "un");
541+
542+
if (!c->authenticated)
543+
return 0;
544+
545+
if (!IS_ENABLED(CONFIG_UBIFS_FS_AUTHENTICATION))
546+
return -EOPNOTSUPP;
547+
548+
hash_algo = le16_to_cpu(sup->hash_algo);
549+
if (hash_algo >= HASH_ALGO__LAST) {
550+
ubifs_err(c, "superblock uses unknown hash algo %d",
551+
hash_algo);
552+
return -EINVAL;
553+
}
554+
555+
if (strcmp(hash_algo_name[hash_algo], c->auth_hash_name)) {
556+
ubifs_err(c, "This filesystem uses %s for hashing,"
557+
" but %s is specified", hash_algo_name[hash_algo],
558+
c->auth_hash_name);
559+
return -EINVAL;
560+
}
561+
562+
err = ubifs_hmac_wkm(c, hmac_wkm);
563+
if (err)
564+
return err;
565+
566+
if (ubifs_check_hmac(c, hmac_wkm, sup->hmac_wkm)) {
567+
ubifs_err(c, "provided key does not fit");
568+
return -ENOKEY;
569+
}
570+
571+
err = ubifs_node_verify_hmac(c, sup, sizeof(*sup),
572+
offsetof(struct ubifs_sb_node, hmac));
573+
if (err)
574+
ubifs_err(c, "Failed to authenticate superblock: %d", err);
575+
576+
return err;
577+
}
578+
520579
/**
521580
* ubifs_write_sb_node - write superblock node.
522581
* @c: UBIFS file-system description object
@@ -527,8 +586,13 @@ static struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c)
527586
int ubifs_write_sb_node(struct ubifs_info *c, struct ubifs_sb_node *sup)
528587
{
529588
int len = ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size);
589+
int err;
590+
591+
err = ubifs_prepare_node_hmac(c, sup, UBIFS_SB_NODE_SZ,
592+
offsetof(struct ubifs_sb_node, hmac), 1);
593+
if (err)
594+
return err;
530595

531-
ubifs_prepare_node(c, sup, UBIFS_SB_NODE_SZ, 1);
532596
return ubifs_leb_change(c, UBIFS_SB_LNUM, sup, len);
533597
}
534598

@@ -642,6 +706,10 @@ int ubifs_read_superblock(struct ubifs_info *c)
642706
c->double_hash = !!(sup_flags & UBIFS_FLG_DOUBLE_HASH);
643707
c->encrypted = !!(sup_flags & UBIFS_FLG_ENCRYPTION);
644708

709+
err = authenticate_sb_node(c, sup);
710+
if (err)
711+
goto out;
712+
645713
if ((sup_flags & ~UBIFS_FLG_MASK) != 0) {
646714
ubifs_err(c, "Unknown feature flags found: %#x",
647715
sup_flags & ~UBIFS_FLG_MASK);

0 commit comments

Comments
 (0)