Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp1930671imm; Fri, 7 Sep 2018 08:16:36 -0700 (PDT) X-Google-Smtp-Source: ANB0VdYz+OAXHAM2mPu94ccP6SXnY7OaJIshLsmeIgwROHaNMEUkPQMv1kxcD7j9xo7wVMU+/kjJ X-Received: by 2002:a17:902:b702:: with SMTP id d2-v6mr8565413pls.12.1536333396848; Fri, 07 Sep 2018 08:16:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1536333396; cv=none; d=google.com; s=arc-20160816; b=lDaNeYU3Nn0MHgl0BD96aopyXtPulUgGBPlG+Tk/F7seWgHoNpAHwk6kTJ8Mlva+uB eTnXUG0+6E9oxMsZZpsqfs/d/uL80eW992RiEhdDpVWQxFW/FETftEeFLcj4RXU9Aohc uAG1S0c0t32ahSY1LQRvX6NNpSB11M/95seb4F4socYkgcoq3PJiXZRDRywnuQLog+sM 0z4L5HlO3pkOMHonPTobMh+td44z5E92cYWIPE7cfD2uIJ7ioVdTYGHyr04dEdbahuA+ SiawtvtdSqymGwt2ytxDIa9qwydqZfK9zU6EtZrkGe+TS3ZE4EhPBujQXi5pgbFO9GAF xCwA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=G9YxQ1fCoD7Vc16NDXKrhZ03gKP+IYR9BLE4yhDsctM=; b=hdsvmwp5UWU+qKhRhg2B4RFIbiMP9ys7Tqhy78slMLkRyiTpt+NZC4KDpXV/0td0yC nqLPIriPRScRbG/cQ8DktjxBP+NReSffZrYtuFvGpsnjGQ2/cnVWSkqy1Rxjc293g/7f I/OiUuFcNHXU4cMUL50x0o68jnFHDdfCna4b4IAYYWBE7bGu9yp6ylf7G9/OvgiYbY1Q aLxEZ3r1b6HpasYu5MwQw4ayzzSpQQyTnDIqOqO3HBSmjIz4cXiM4zvTicqxbqS/LAom 2q3qVOzK9im5CcFLk0IyDjoZX1viGp/wtzQucgF2Tw3XG9+7dDGy9Fl3Oxpk2DPwvoNZ 4/bg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 184-v6si6394338pgi.614.2018.09.07.08.16.19; Fri, 07 Sep 2018 08:16:36 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728510AbeIGRU0 (ORCPT + 99 others); Fri, 7 Sep 2018 13:20:26 -0400 Received: from metis.ext.pengutronix.de ([85.220.165.71]:33929 "EHLO metis.ext.pengutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729216AbeIGRTk (ORCPT ); Fri, 7 Sep 2018 13:19:40 -0400 Received: from dude.hi.pengutronix.de ([2001:67c:670:100:1d::7]) by metis.ext.pengutronix.de with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1fyG27-0007c4-RC; Fri, 07 Sep 2018 14:38:43 +0200 Received: from sha by dude.hi.pengutronix.de with local (Exim 4.91) (envelope-from ) id 1fyG26-00062X-Iz; Fri, 07 Sep 2018 14:38:42 +0200 From: Sascha Hauer To: linux-mtd@lists.infradead.org Cc: David Gstir , Richard Weinberger , kernel@pengutronix.de, linux-kernel@vger.kernel.org, Sascha Hauer Subject: [PATCH 19/25] ubfis: authentication: authenticate master node Date: Fri, 7 Sep 2018 14:36:40 +0200 Message-Id: <20180907123646.12688-20-s.hauer@pengutronix.de> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180907123646.12688-1-s.hauer@pengutronix.de> References: <20180907123646.12688-1-s.hauer@pengutronix.de> X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::7 X-SA-Exim-Mail-From: sha@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-kernel@vger.kernel.org Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The master node contains hashes over the root index node and the LPT. This patch adds a HMAC to authenticate the master node itself. Signed-off-by: Sascha Hauer --- fs/ubifs/master.c | 61 ++++++++++++++++++++++++++++++++++++++++----- fs/ubifs/recovery.c | 9 ++++--- fs/ubifs/ubifs.h | 1 + 3 files changed, 61 insertions(+), 10 deletions(-) diff --git a/fs/ubifs/master.c b/fs/ubifs/master.c index 0ca9d3513b4d..5ea51bbd14c7 100644 --- a/fs/ubifs/master.c +++ b/fs/ubifs/master.c @@ -24,6 +24,42 @@ #include "ubifs.h" +/** + * ubifs_compare_master_node - compare two UBIFS master nodes + * @c: UBIFS file-system description object + * @m1: the first node + * @m2: the second node + * + * This function compares two UBIFS master nodes. Returns 0 if they are equal + * and nonzero if not. + */ +int ubifs_compare_master_node(struct ubifs_info *c, void *m1, void *m2) +{ + int ret; + int behind; + int hmac_offs = offsetof(struct ubifs_mst_node, hmac); + + /* + * Do not compare the common node header since the sequence number and + * hence the CRC are different. + */ + ret = memcmp(m1 + UBIFS_CH_SZ, m2 + UBIFS_CH_SZ, + hmac_offs - UBIFS_CH_SZ); + if (ret) + return ret; + + /* + * Do not compare the embedded HMAC aswell which also must be different + * due to the different common node header. + */ + behind = hmac_offs + UBIFS_MAX_HMAC_LEN; + + if (UBIFS_MST_NODE_SZ > behind) + return memcmp(m1 + behind, m2 + behind, UBIFS_MST_NODE_SZ - behind); + + return 0; +} + /** * scan_for_master - search the valid master node. * @c: UBIFS file-system description object @@ -37,7 +73,7 @@ static int scan_for_master(struct ubifs_info *c) { struct ubifs_scan_leb *sleb; struct ubifs_scan_node *snod; - int lnum, offs = 0, nodes_cnt; + int lnum, offs = 0, nodes_cnt, err; lnum = UBIFS_MST_LNUM; @@ -69,12 +105,23 @@ static int scan_for_master(struct ubifs_info *c) goto out_dump; if (snod->offs != offs) goto out; - if (memcmp((void *)c->mst_node + UBIFS_CH_SZ, - (void *)snod->node + UBIFS_CH_SZ, - UBIFS_MST_NODE_SZ - UBIFS_CH_SZ)) + if (ubifs_compare_master_node(c, c->mst_node, snod->node)) goto out; + c->mst_offs = offs; ubifs_scan_destroy(sleb); + + if (!ubifs_authenticated(c)) + return 0; + + err = ubifs_node_verify_hmac(c, c->mst_node, + sizeof(struct ubifs_mst_node), + offsetof(struct ubifs_mst_node, hmac)); + if (err) { + ubifs_err(c, "Failed to verify master node HMAC"); + return -EPERM; + } + return 0; out: @@ -381,7 +428,8 @@ int ubifs_write_master(struct ubifs_info *c) c->mst_node->highest_inum = cpu_to_le64(c->highest_inum); ubifs_copy_hash(c, c->zroot.hash, c->mst_node->hash_root_idx); - err = ubifs_write_node(c, c->mst_node, len, lnum, offs); + err = ubifs_write_node_hmac(c, c->mst_node, len, lnum, offs, + offsetof(struct ubifs_mst_node, hmac)); if (err) return err; @@ -392,7 +440,8 @@ int ubifs_write_master(struct ubifs_info *c) if (err) return err; } - err = ubifs_write_node(c, c->mst_node, len, lnum, offs); + err = ubifs_write_node_hmac(c, c->mst_node, len, lnum, offs, + offsetof(struct ubifs_mst_node, hmac)); return err; } diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index 984e30e83c0b..5c1334e6bc81 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c @@ -212,7 +212,10 @@ static int write_rcvrd_mst_node(struct ubifs_info *c, save_flags = mst->flags; mst->flags |= cpu_to_le32(UBIFS_MST_RCVRY); - ubifs_prepare_node(c, mst, UBIFS_MST_NODE_SZ, 1); + err = ubifs_prepare_node_hmac(c, mst, UBIFS_MST_NODE_SZ, + offsetof(struct ubifs_mst_node, hmac), 1); + if (err) + goto out; err = ubifs_leb_change(c, lnum, mst, sz); if (err) goto out; @@ -264,9 +267,7 @@ int ubifs_recover_master_node(struct ubifs_info *c) offs2 = (void *)mst2 - buf2; if (offs1 == offs2) { /* Same offset, so must be the same */ - if (memcmp((void *)mst1 + UBIFS_CH_SZ, - (void *)mst2 + UBIFS_CH_SZ, - UBIFS_MST_NODE_SZ - UBIFS_CH_SZ)) + if (ubifs_compare_master_node(c, mst1, mst2)) goto out_err; mst = mst1; } else if (offs2 + sz == offs1) { diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 7e519a4885a8..c26d3c600e4d 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1900,6 +1900,7 @@ int ubifs_gc_should_commit(struct ubifs_info *c); void ubifs_wait_for_commit(struct ubifs_info *c); /* master.c */ +int ubifs_compare_master_node(struct ubifs_info *c, void *m1, void *m2); int ubifs_read_master(struct ubifs_info *c); int ubifs_write_master(struct ubifs_info *c); -- 2.18.0