aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2018-09-07 08:36:40 -0400
committerRichard Weinberger <richard@nod.at>2018-10-23 07:48:52 -0400
commit625700ccb5069ec81d15aae3b47282ecc59d63b5 (patch)
treef0c25183cc69de8ab9377aeb143006ee67d2a5e9
parenta1dc58140f7e63e3b23050eb43b4e5581cb28c88 (diff)
ubfis: authentication: Authenticate master node
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 <s.hauer@pengutronix.de> Signed-off-by: Richard Weinberger <richard@nod.at>
-rw-r--r--fs/ubifs/master.c61
-rw-r--r--fs/ubifs/recovery.c9
-rw-r--r--fs/ubifs/ubifs.h1
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
@@ -25,6 +25,42 @@
25#include "ubifs.h" 25#include "ubifs.h"
26 26
27/** 27/**
28 * ubifs_compare_master_node - compare two UBIFS master nodes
29 * @c: UBIFS file-system description object
30 * @m1: the first node
31 * @m2: the second node
32 *
33 * This function compares two UBIFS master nodes. Returns 0 if they are equal
34 * and nonzero if not.
35 */
36int ubifs_compare_master_node(struct ubifs_info *c, void *m1, void *m2)
37{
38 int ret;
39 int behind;
40 int hmac_offs = offsetof(struct ubifs_mst_node, hmac);
41
42 /*
43 * Do not compare the common node header since the sequence number and
44 * hence the CRC are different.
45 */
46 ret = memcmp(m1 + UBIFS_CH_SZ, m2 + UBIFS_CH_SZ,
47 hmac_offs - UBIFS_CH_SZ);
48 if (ret)
49 return ret;
50
51 /*
52 * Do not compare the embedded HMAC aswell which also must be different
53 * due to the different common node header.
54 */
55 behind = hmac_offs + UBIFS_MAX_HMAC_LEN;
56
57 if (UBIFS_MST_NODE_SZ > behind)
58 return memcmp(m1 + behind, m2 + behind, UBIFS_MST_NODE_SZ - behind);
59
60 return 0;
61}
62
63/**
28 * scan_for_master - search the valid master node. 64 * scan_for_master - search the valid master node.
29 * @c: UBIFS file-system description object 65 * @c: UBIFS file-system description object
30 * 66 *
@@ -37,7 +73,7 @@ static int scan_for_master(struct ubifs_info *c)
37{ 73{
38 struct ubifs_scan_leb *sleb; 74 struct ubifs_scan_leb *sleb;
39 struct ubifs_scan_node *snod; 75 struct ubifs_scan_node *snod;
40 int lnum, offs = 0, nodes_cnt; 76 int lnum, offs = 0, nodes_cnt, err;
41 77
42 lnum = UBIFS_MST_LNUM; 78 lnum = UBIFS_MST_LNUM;
43 79
@@ -69,12 +105,23 @@ static int scan_for_master(struct ubifs_info *c)
69 goto out_dump; 105 goto out_dump;
70 if (snod->offs != offs) 106 if (snod->offs != offs)
71 goto out; 107 goto out;
72 if (memcmp((void *)c->mst_node + UBIFS_CH_SZ, 108 if (ubifs_compare_master_node(c, c->mst_node, snod->node))
73 (void *)snod->node + UBIFS_CH_SZ,
74 UBIFS_MST_NODE_SZ - UBIFS_CH_SZ))
75 goto out; 109 goto out;
110
76 c->mst_offs = offs; 111 c->mst_offs = offs;
77 ubifs_scan_destroy(sleb); 112 ubifs_scan_destroy(sleb);
113
114 if (!ubifs_authenticated(c))
115 return 0;
116
117 err = ubifs_node_verify_hmac(c, c->mst_node,
118 sizeof(struct ubifs_mst_node),
119 offsetof(struct ubifs_mst_node, hmac));
120 if (err) {
121 ubifs_err(c, "Failed to verify master node HMAC");
122 return -EPERM;
123 }
124
78 return 0; 125 return 0;
79 126
80out: 127out:
@@ -381,7 +428,8 @@ int ubifs_write_master(struct ubifs_info *c)
381 c->mst_node->highest_inum = cpu_to_le64(c->highest_inum); 428 c->mst_node->highest_inum = cpu_to_le64(c->highest_inum);
382 429
383 ubifs_copy_hash(c, c->zroot.hash, c->mst_node->hash_root_idx); 430 ubifs_copy_hash(c, c->zroot.hash, c->mst_node->hash_root_idx);
384 err = ubifs_write_node(c, c->mst_node, len, lnum, offs); 431 err = ubifs_write_node_hmac(c, c->mst_node, len, lnum, offs,
432 offsetof(struct ubifs_mst_node, hmac));
385 if (err) 433 if (err)
386 return err; 434 return err;
387 435
@@ -392,7 +440,8 @@ int ubifs_write_master(struct ubifs_info *c)
392 if (err) 440 if (err)
393 return err; 441 return err;
394 } 442 }
395 err = ubifs_write_node(c, c->mst_node, len, lnum, offs); 443 err = ubifs_write_node_hmac(c, c->mst_node, len, lnum, offs,
444 offsetof(struct ubifs_mst_node, hmac));
396 445
397 return err; 446 return err;
398} 447}
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,
212 save_flags = mst->flags; 212 save_flags = mst->flags;
213 mst->flags |= cpu_to_le32(UBIFS_MST_RCVRY); 213 mst->flags |= cpu_to_le32(UBIFS_MST_RCVRY);
214 214
215 ubifs_prepare_node(c, mst, UBIFS_MST_NODE_SZ, 1); 215 err = ubifs_prepare_node_hmac(c, mst, UBIFS_MST_NODE_SZ,
216 offsetof(struct ubifs_mst_node, hmac), 1);
217 if (err)
218 goto out;
216 err = ubifs_leb_change(c, lnum, mst, sz); 219 err = ubifs_leb_change(c, lnum, mst, sz);
217 if (err) 220 if (err)
218 goto out; 221 goto out;
@@ -264,9 +267,7 @@ int ubifs_recover_master_node(struct ubifs_info *c)
264 offs2 = (void *)mst2 - buf2; 267 offs2 = (void *)mst2 - buf2;
265 if (offs1 == offs2) { 268 if (offs1 == offs2) {
266 /* Same offset, so must be the same */ 269 /* Same offset, so must be the same */
267 if (memcmp((void *)mst1 + UBIFS_CH_SZ, 270 if (ubifs_compare_master_node(c, mst1, mst2))
268 (void *)mst2 + UBIFS_CH_SZ,
269 UBIFS_MST_NODE_SZ - UBIFS_CH_SZ))
270 goto out_err; 271 goto out_err;
271 mst = mst1; 272 mst = mst1;
272 } else if (offs2 + sz == offs1) { 273 } 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);
1900void ubifs_wait_for_commit(struct ubifs_info *c); 1900void ubifs_wait_for_commit(struct ubifs_info *c);
1901 1901
1902/* master.c */ 1902/* master.c */
1903int ubifs_compare_master_node(struct ubifs_info *c, void *m1, void *m2);
1903int ubifs_read_master(struct ubifs_info *c); 1904int ubifs_read_master(struct ubifs_info *c);
1904int ubifs_write_master(struct ubifs_info *c); 1905int ubifs_write_master(struct ubifs_info *c);
1905 1906