linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sascha Hauer <s.hauer@pengutronix.de>
To: linux-mtd@lists.infradead.org
Cc: David Gstir <david@sigma-star.at>,
	Richard Weinberger <richard@nod.at>,
	kernel@pengutronix.de, linux-kernel@vger.kernel.org,
	Sascha Hauer <s.hauer@pengutronix.de>
Subject: [PATCH 17/25] ubifs: authentication: authenticate LPT
Date: Wed,  4 Jul 2018 14:41:29 +0200	[thread overview]
Message-ID: <20180704124137.13396-18-s.hauer@pengutronix.de> (raw)
In-Reply-To: <20180704124137.13396-1-s.hauer@pengutronix.de>

The LPT needs to be authenticated aswell. Since the LPT is only written
during commit it is enough to authenticate the whole LPT with a single
hash which is stored in the master node. Only the leaf nodes (pnodes)
are hashed which makes the implementation much simpler than it would be
to hash the complete LPT.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 fs/ubifs/lpt.c        | 127 ++++++++++++++++++++++++++++++++++++++++++
 fs/ubifs/lpt_commit.c |   4 ++
 fs/ubifs/ubifs.h      |   1 +
 3 files changed, 132 insertions(+)

diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c
index cde7b9484157..2c440bb31d69 100644
--- a/fs/ubifs/lpt.c
+++ b/fs/ubifs/lpt.c
@@ -1633,6 +1633,129 @@ struct ubifs_lprops *ubifs_lpt_lookup_dirty(struct ubifs_info *c, int lnum)
 	return &pnode->lprops[iip];
 }
 
+/**
+ * ubifs_lpt_calc_hash - Calculate hash of the LPT pnodes
+ * @c: UBIFS file-system description object
+ * @hash: the returned hash of the LPT pnodes
+ *
+ * This function iterates over the LPT pnodes and creates a hash over them.
+ * Returns 0 for success or a negative error code otherwise.
+ */
+int ubifs_lpt_calc_hash(struct ubifs_info *c, u8 *hash)
+{
+	struct ubifs_nnode *nnode, *nn;
+	struct ubifs_cnode *cnode;
+	struct shash_desc *desc;
+	int iip = 0, i;
+	int bufsiz = max_t(int, c->nnode_sz, c->pnode_sz);
+	void *buf;
+	int err;
+
+	if (!ubifs_authenticated(c))
+		return 0;
+
+	desc = ubifs_hash_get_desc(c);
+	if (IS_ERR(desc))
+		return PTR_ERR(desc);
+
+	buf = kmalloc(bufsiz, GFP_NOFS);
+	if (!buf) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	if (!c->nroot) {
+		err = ubifs_read_nnode(c, NULL, 0);
+		if (err)
+			return err;
+	}
+
+	cnode = (struct ubifs_cnode *)c->nroot;
+
+	while (cnode) {
+		nnode = cnode->parent;
+		nn = (struct ubifs_nnode *)cnode;
+		if (cnode->level > 1) {
+			while (iip < UBIFS_LPT_FANOUT) {
+				if (nn->nbranch[iip].lnum == 0) {
+					/* Go right */
+					iip++;
+					continue;
+				}
+
+				nnode = ubifs_get_nnode(c, nn, iip);
+				if (IS_ERR(nnode)) {
+					err = PTR_ERR(nnode);
+					goto out;
+				}
+
+				/* Go down */
+				iip = 0;
+				cnode = (struct ubifs_cnode *)nnode;
+				break;
+			}
+			if (iip < UBIFS_LPT_FANOUT)
+				continue;
+		} else {
+			struct ubifs_pnode *pnode;
+
+			for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
+				if (nn->nbranch[i].lnum == 0)
+					continue;
+				pnode = ubifs_get_pnode(c, nn, i);
+				if (IS_ERR(pnode)) {
+					err = PTR_ERR(pnode);
+					goto out;
+				}
+
+				ubifs_pack_pnode(c, buf, pnode);
+				ubifs_shash_update(c, desc, buf, c->pnode_sz);
+			}
+		}
+		/* Go up and to the right */
+		iip = cnode->iip + 1;
+		cnode = (struct ubifs_cnode *)nnode;
+	}
+
+	err = 0;
+	ubifs_shash_final(c, desc, hash);
+out:
+	kfree(desc);
+	kfree(buf);
+
+	return err;
+}
+
+/**
+ * lpt_check_hash - check the hash of the LPT.
+ * @c: UBIFS file-system description object
+ *
+ * This function calculates a hash over all pnodes in the LPT and compares it with
+ * the hash stored in the master node. Returns %0 on success and a negative error
+ * code on failure.
+ */
+static int lpt_check_hash(struct ubifs_info *c)
+{
+	int err;
+	u8 hash[UBIFS_MAX_HASH_LEN];
+
+	if (!ubifs_authenticated(c))
+		return 0;
+
+	err = ubifs_lpt_calc_hash(c, hash);
+	if (err)
+		return err;
+
+	if (ubifs_check_hash(c, c->mst_node->hash_lpt, hash)) {
+		err = -EPERM;
+		ubifs_err(c, "Failed to authenticate LPT");
+	} else {
+		err = 0;
+	}
+
+	return err;
+}
+
 /**
  * lpt_init_rd - initialize the LPT for reading.
  * @c: UBIFS file-system description object
@@ -1674,6 +1797,10 @@ static int lpt_init_rd(struct ubifs_info *c)
 	if (err)
 		return err;
 
+	err = lpt_check_hash(c);
+	if (err)
+		return err;
+
 	dbg_lp("space_bits %d", c->space_bits);
 	dbg_lp("lpt_lnum_bits %d", c->lpt_lnum_bits);
 	dbg_lp("lpt_offs_bits %d", c->lpt_offs_bits);
diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c
index 14e72d09b6b3..817586f4962c 100644
--- a/fs/ubifs/lpt_commit.c
+++ b/fs/ubifs/lpt_commit.c
@@ -1245,6 +1245,10 @@ int ubifs_lpt_start_commit(struct ubifs_info *c)
 	if (err)
 		goto out;
 
+	err = ubifs_lpt_calc_hash(c, c->mst_node->hash_lpt);
+	if (err)
+		goto out;
+
 	/* Copy the LPT's own lprops for end commit to write */
 	memcpy(c->ltab_cmt, c->ltab,
 	       sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs);
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 5390d087da3a..5234a7c9380c 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -1913,6 +1913,7 @@ struct ubifs_nnode *ubifs_first_nnode(struct ubifs_info *c, int *hght);
 /* Needed only in debugging code in lpt_commit.c */
 int ubifs_unpack_nnode(const struct ubifs_info *c, void *buf,
 		       struct ubifs_nnode *nnode);
+int ubifs_lpt_calc_hash(struct ubifs_info *c, u8 *hash);
 
 /* lpt_commit.c */
 int ubifs_lpt_start_commit(struct ubifs_info *c);
-- 
2.18.0


  parent reply	other threads:[~2018-07-04 12:44 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-07-04 12:41 [PATCH 00/25] UBIFS authentication support Sascha Hauer
2018-07-04 12:41 ` [PATCH 01/25] ubifs: refactor create_default_filesystem() Sascha Hauer
2018-07-04 12:41 ` [PATCH 02/25] ubifs: pass ubifs_zbranch to try_read_node() Sascha Hauer
2018-07-04 12:41 ` [PATCH 03/25] ubifs: pass ubifs_zbranch to read_znode() Sascha Hauer
2018-07-04 12:41 ` [PATCH 04/25] ubifs: export pnode_lookup as ubifs_pnode_lookup Sascha Hauer
2018-07-04 12:41 ` [PATCH 05/25] ubifs: implement ubifs_lpt_lookup using ubifs_pnode_lookup Sascha Hauer
2018-08-13  6:31   ` Sascha Hauer
2018-08-13  6:34     ` Richard Weinberger
2018-08-13  8:12       ` Sascha Hauer
2018-08-13 11:30         ` Richard Weinberger
2018-08-26 20:59     ` Richard Weinberger
2018-07-04 12:41 ` [PATCH 06/25] ubifs: drop write_node Sascha Hauer
2018-07-04 12:41 ` [PATCH 07/25] ubifs: Store read superblock node Sascha Hauer
2018-08-27 12:50   ` Richard Weinberger
2018-07-04 12:41 ` [PATCH 08/25] ubifs: Format changes for authentication support Sascha Hauer
2018-07-04 12:41 ` [PATCH 09/25] ubifs: add separate functions to init/crc a node Sascha Hauer
2018-07-04 12:41 ` [PATCH 10/25] ubifs: add helper functions for authentication support Sascha Hauer
2018-08-27 12:50   ` Richard Weinberger
2018-08-29  6:30     ` Sascha Hauer
2018-07-04 12:41 ` [PATCH 11/25] ubifs: Create functions to embed a HMAC in a node Sascha Hauer
2018-07-04 12:41 ` [PATCH 12/25] ubifs: Add hashes to the tree node cache Sascha Hauer
2018-08-27 19:18   ` Richard Weinberger
2018-08-29 11:16     ` Sascha Hauer
2018-07-04 12:41 ` [PATCH 13/25] ubifs: authentication: Add hashes to index nodes Sascha Hauer
2018-08-27 19:36   ` Richard Weinberger
2018-09-07 10:25     ` Sascha Hauer
2018-07-04 12:41 ` [PATCH 14/25] ubifs: Add authentication nodes to journal Sascha Hauer
2018-07-08  2:59   ` kbuild test robot
2018-08-27 20:48   ` Richard Weinberger
2018-08-29 14:38     ` Sascha Hauer
2018-08-29 14:54       ` Richard Weinberger
2018-08-30 13:41         ` Sascha Hauer
2018-09-02 19:45       ` Richard Weinberger
2018-07-04 12:41 ` [PATCH 15/25] ubifs: Add auth nodes to garbage collector journal head Sascha Hauer
2018-08-27 20:51   ` Richard Weinberger
2018-08-30 14:43     ` Sascha Hauer
2018-07-04 12:41 ` [PATCH 16/25] ubifs: authenticate replayed journal Sascha Hauer
2018-07-08  6:08   ` kbuild test robot
2018-08-27 21:16   ` Richard Weinberger
2018-07-04 12:41 ` Sascha Hauer [this message]
2018-07-04 12:41 ` [PATCH 18/25] ubfis: authentication: authenticate master node Sascha Hauer
2018-07-04 12:41 ` [PATCH 19/25] ubifs: Create hash for default LPT Sascha Hauer
2018-07-04 12:41 ` [PATCH 20/25] ubifs: authentication: Authenticate super block node Sascha Hauer
2018-07-04 12:41 ` [PATCH 21/25] ubifs: Add hashes and HMACs to default filesystem Sascha Hauer
2018-07-04 12:41 ` [PATCH 22/25] ubifs: do not update inode size in-place in authenticated mode Sascha Hauer
2018-07-04 12:41 ` [PATCH 23/25] ubifs: Enable authentication support Sascha Hauer
2018-07-04 12:41 ` [PATCH 24/25] ubifs: support offline signed images Sascha Hauer
2018-07-04 12:41 ` [PATCH 25/25] Documentation: ubifs: Add authentication whitepaper Sascha Hauer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180704124137.13396-18-s.hauer@pengutronix.de \
    --to=s.hauer@pengutronix.de \
    --cc=david@sigma-star.at \
    --cc=kernel@pengutronix.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=richard@nod.at \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).