diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2018-09-07 08:36:30 -0400 |
---|---|---|
committer | Richard Weinberger <richard@nod.at> | 2018-10-23 07:48:29 -0400 |
commit | 5125cfdff13a4da4c34a053cd67e99083aece028 (patch) | |
tree | b2735cff5c7ee523b1b21ba1faa0b87c5a08c834 | |
parent | fd6150051becd3a9f8039046e3af91fd9ef01e57 (diff) |
ubifs: Format changes for authentication support
This patch adds the changes to the on disk format needed for
authentication support. We'll add:
* a HMAC covering super block node
* a HMAC covering the master node
* a hash over the root index node to the master node
* a hash over the LPT to the master node
* a flag to the filesystem flag indicating the filesystem is
authenticated
* an authentication node necessary to authenticate the nodes written
to the journal heads while they are written.
* a HMAC of a well known message to the super block node to be able
to check if the correct key is provided
And finally, not visible in this patch, nevertheless explained here:
* hashes over the referenced child nodes in each branch of a index node
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Richard Weinberger <richard@nod.at>
-rw-r--r-- | fs/ubifs/debug.c | 6 | ||||
-rw-r--r-- | fs/ubifs/super.c | 1 | ||||
-rw-r--r-- | fs/ubifs/ubifs-media.h | 46 |
3 files changed, 50 insertions, 3 deletions
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 564e330d05b1..c49ff50fdceb 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c | |||
@@ -165,6 +165,8 @@ const char *dbg_ntype(int type) | |||
165 | return "commit start node"; | 165 | return "commit start node"; |
166 | case UBIFS_ORPH_NODE: | 166 | case UBIFS_ORPH_NODE: |
167 | return "orphan node"; | 167 | return "orphan node"; |
168 | case UBIFS_AUTH_NODE: | ||
169 | return "auth node"; | ||
168 | default: | 170 | default: |
169 | return "unknown node"; | 171 | return "unknown node"; |
170 | } | 172 | } |
@@ -542,6 +544,10 @@ void ubifs_dump_node(const struct ubifs_info *c, const void *node) | |||
542 | (unsigned long long)le64_to_cpu(orph->inos[i])); | 544 | (unsigned long long)le64_to_cpu(orph->inos[i])); |
543 | break; | 545 | break; |
544 | } | 546 | } |
547 | case UBIFS_AUTH_NODE: | ||
548 | { | ||
549 | break; | ||
550 | } | ||
545 | default: | 551 | default: |
546 | pr_err("node type %d was not recognized\n", | 552 | pr_err("node type %d was not recognized\n", |
547 | (int)ch->node_type); | 553 | (int)ch->node_type); |
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 70a64e00f0a8..0194e3c0853f 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
@@ -579,6 +579,7 @@ static int init_constants_early(struct ubifs_info *c) | |||
579 | c->ranges[UBIFS_REF_NODE].len = UBIFS_REF_NODE_SZ; | 579 | c->ranges[UBIFS_REF_NODE].len = UBIFS_REF_NODE_SZ; |
580 | c->ranges[UBIFS_TRUN_NODE].len = UBIFS_TRUN_NODE_SZ; | 580 | c->ranges[UBIFS_TRUN_NODE].len = UBIFS_TRUN_NODE_SZ; |
581 | c->ranges[UBIFS_CS_NODE].len = UBIFS_CS_NODE_SZ; | 581 | c->ranges[UBIFS_CS_NODE].len = UBIFS_CS_NODE_SZ; |
582 | c->ranges[UBIFS_AUTH_NODE].len = UBIFS_AUTH_NODE_SZ; | ||
582 | 583 | ||
583 | c->ranges[UBIFS_INO_NODE].min_len = UBIFS_INO_NODE_SZ; | 584 | c->ranges[UBIFS_INO_NODE].min_len = UBIFS_INO_NODE_SZ; |
584 | c->ranges[UBIFS_INO_NODE].max_len = UBIFS_MAX_INO_NODE_SZ; | 585 | c->ranges[UBIFS_INO_NODE].max_len = UBIFS_MAX_INO_NODE_SZ; |
diff --git a/fs/ubifs/ubifs-media.h b/fs/ubifs/ubifs-media.h index e8c23c9d4f4a..8b7c1844014f 100644 --- a/fs/ubifs/ubifs-media.h +++ b/fs/ubifs/ubifs-media.h | |||
@@ -286,6 +286,7 @@ enum { | |||
286 | #define UBIFS_IDX_NODE_SZ sizeof(struct ubifs_idx_node) | 286 | #define UBIFS_IDX_NODE_SZ sizeof(struct ubifs_idx_node) |
287 | #define UBIFS_CS_NODE_SZ sizeof(struct ubifs_cs_node) | 287 | #define UBIFS_CS_NODE_SZ sizeof(struct ubifs_cs_node) |
288 | #define UBIFS_ORPH_NODE_SZ sizeof(struct ubifs_orph_node) | 288 | #define UBIFS_ORPH_NODE_SZ sizeof(struct ubifs_orph_node) |
289 | #define UBIFS_AUTH_NODE_SZ sizeof(struct ubifs_auth_node) | ||
289 | /* Extended attribute entry nodes are identical to directory entry nodes */ | 290 | /* Extended attribute entry nodes are identical to directory entry nodes */ |
290 | #define UBIFS_XENT_NODE_SZ UBIFS_DENT_NODE_SZ | 291 | #define UBIFS_XENT_NODE_SZ UBIFS_DENT_NODE_SZ |
291 | /* Only this does not have to be multiple of 8 bytes */ | 292 | /* Only this does not have to be multiple of 8 bytes */ |
@@ -300,6 +301,12 @@ enum { | |||
300 | /* The largest UBIFS node */ | 301 | /* The largest UBIFS node */ |
301 | #define UBIFS_MAX_NODE_SZ UBIFS_MAX_INO_NODE_SZ | 302 | #define UBIFS_MAX_NODE_SZ UBIFS_MAX_INO_NODE_SZ |
302 | 303 | ||
304 | /* The maxmimum size of a hash, enough for sha512 */ | ||
305 | #define UBIFS_MAX_HASH_LEN 64 | ||
306 | |||
307 | /* The maxmimum size of a hmac, enough for hmac(sha512) */ | ||
308 | #define UBIFS_MAX_HMAC_LEN 64 | ||
309 | |||
303 | /* | 310 | /* |
304 | * xattr name of UBIFS encryption context, we don't use a prefix | 311 | * xattr name of UBIFS encryption context, we don't use a prefix |
305 | * nor a long name to not waste space on the flash. | 312 | * nor a long name to not waste space on the flash. |
@@ -365,6 +372,7 @@ enum { | |||
365 | * UBIFS_IDX_NODE: index node | 372 | * UBIFS_IDX_NODE: index node |
366 | * UBIFS_CS_NODE: commit start node | 373 | * UBIFS_CS_NODE: commit start node |
367 | * UBIFS_ORPH_NODE: orphan node | 374 | * UBIFS_ORPH_NODE: orphan node |
375 | * UBIFS_AUTH_NODE: authentication node | ||
368 | * UBIFS_NODE_TYPES_CNT: count of supported node types | 376 | * UBIFS_NODE_TYPES_CNT: count of supported node types |
369 | * | 377 | * |
370 | * Note, we index arrays by these numbers, so keep them low and contiguous. | 378 | * Note, we index arrays by these numbers, so keep them low and contiguous. |
@@ -384,6 +392,7 @@ enum { | |||
384 | UBIFS_IDX_NODE, | 392 | UBIFS_IDX_NODE, |
385 | UBIFS_CS_NODE, | 393 | UBIFS_CS_NODE, |
386 | UBIFS_ORPH_NODE, | 394 | UBIFS_ORPH_NODE, |
395 | UBIFS_AUTH_NODE, | ||
387 | UBIFS_NODE_TYPES_CNT, | 396 | UBIFS_NODE_TYPES_CNT, |
388 | }; | 397 | }; |
389 | 398 | ||
@@ -421,15 +430,19 @@ enum { | |||
421 | * UBIFS_FLG_DOUBLE_HASH: store a 32bit cookie in directory entry nodes to | 430 | * UBIFS_FLG_DOUBLE_HASH: store a 32bit cookie in directory entry nodes to |
422 | * support 64bit cookies for lookups by hash | 431 | * support 64bit cookies for lookups by hash |
423 | * UBIFS_FLG_ENCRYPTION: this filesystem contains encrypted files | 432 | * UBIFS_FLG_ENCRYPTION: this filesystem contains encrypted files |
433 | * UBIFS_FLG_AUTHENTICATION: this filesystem contains hashes for authentication | ||
424 | */ | 434 | */ |
425 | enum { | 435 | enum { |
426 | UBIFS_FLG_BIGLPT = 0x02, | 436 | UBIFS_FLG_BIGLPT = 0x02, |
427 | UBIFS_FLG_SPACE_FIXUP = 0x04, | 437 | UBIFS_FLG_SPACE_FIXUP = 0x04, |
428 | UBIFS_FLG_DOUBLE_HASH = 0x08, | 438 | UBIFS_FLG_DOUBLE_HASH = 0x08, |
429 | UBIFS_FLG_ENCRYPTION = 0x10, | 439 | UBIFS_FLG_ENCRYPTION = 0x10, |
440 | UBIFS_FLG_AUTHENTICATION = 0x20, | ||
430 | }; | 441 | }; |
431 | 442 | ||
432 | #define UBIFS_FLG_MASK (UBIFS_FLG_BIGLPT|UBIFS_FLG_SPACE_FIXUP|UBIFS_FLG_DOUBLE_HASH|UBIFS_FLG_ENCRYPTION) | 443 | #define UBIFS_FLG_MASK (UBIFS_FLG_BIGLPT | UBIFS_FLG_SPACE_FIXUP | \ |
444 | UBIFS_FLG_DOUBLE_HASH | UBIFS_FLG_ENCRYPTION | \ | ||
445 | UBIFS_FLG_AUTHENTICATION) | ||
433 | 446 | ||
434 | /** | 447 | /** |
435 | * struct ubifs_ch - common header node. | 448 | * struct ubifs_ch - common header node. |
@@ -633,6 +646,10 @@ struct ubifs_pad_node { | |||
633 | * @time_gran: time granularity in nanoseconds | 646 | * @time_gran: time granularity in nanoseconds |
634 | * @uuid: UUID generated when the file system image was created | 647 | * @uuid: UUID generated when the file system image was created |
635 | * @ro_compat_version: UBIFS R/O compatibility version | 648 | * @ro_compat_version: UBIFS R/O compatibility version |
649 | * @hmac: HMAC to authenticate the superblock node | ||
650 | * @hmac_wkm: HMAC of a well known message (the string "UBIFS") as a convenience | ||
651 | * to the user to check if the correct key is passed. | ||
652 | * @hash_algo: The hash algo used for this filesystem (one of enum hash_algo) | ||
636 | */ | 653 | */ |
637 | struct ubifs_sb_node { | 654 | struct ubifs_sb_node { |
638 | struct ubifs_ch ch; | 655 | struct ubifs_ch ch; |
@@ -660,7 +677,10 @@ struct ubifs_sb_node { | |||
660 | __le32 time_gran; | 677 | __le32 time_gran; |
661 | __u8 uuid[16]; | 678 | __u8 uuid[16]; |
662 | __le32 ro_compat_version; | 679 | __le32 ro_compat_version; |
663 | __u8 padding2[3968]; | 680 | __u8 hmac[UBIFS_MAX_HMAC_LEN]; |
681 | __u8 hmac_wkm[UBIFS_MAX_HMAC_LEN]; | ||
682 | __le16 hash_algo; | ||
683 | __u8 padding2[3838]; | ||
664 | } __packed; | 684 | } __packed; |
665 | 685 | ||
666 | /** | 686 | /** |
@@ -695,6 +715,9 @@ struct ubifs_sb_node { | |||
695 | * @empty_lebs: number of empty logical eraseblocks | 715 | * @empty_lebs: number of empty logical eraseblocks |
696 | * @idx_lebs: number of indexing logical eraseblocks | 716 | * @idx_lebs: number of indexing logical eraseblocks |
697 | * @leb_cnt: count of LEBs used by file-system | 717 | * @leb_cnt: count of LEBs used by file-system |
718 | * @hash_root_idx: the hash of the root index node | ||
719 | * @hash_lpt: the hash of the LPT | ||
720 | * @hmac: HMAC to authenticate the master node | ||
698 | * @padding: reserved for future, zeroes | 721 | * @padding: reserved for future, zeroes |
699 | */ | 722 | */ |
700 | struct ubifs_mst_node { | 723 | struct ubifs_mst_node { |
@@ -727,7 +750,10 @@ struct ubifs_mst_node { | |||
727 | __le32 empty_lebs; | 750 | __le32 empty_lebs; |
728 | __le32 idx_lebs; | 751 | __le32 idx_lebs; |
729 | __le32 leb_cnt; | 752 | __le32 leb_cnt; |
730 | __u8 padding[344]; | 753 | __u8 hash_root_idx[UBIFS_MAX_HASH_LEN]; |
754 | __u8 hash_lpt[UBIFS_MAX_HASH_LEN]; | ||
755 | __u8 hmac[UBIFS_MAX_HMAC_LEN]; | ||
756 | __u8 padding[152]; | ||
731 | } __packed; | 757 | } __packed; |
732 | 758 | ||
733 | /** | 759 | /** |
@@ -747,11 +773,25 @@ struct ubifs_ref_node { | |||
747 | } __packed; | 773 | } __packed; |
748 | 774 | ||
749 | /** | 775 | /** |
776 | * struct ubifs_auth_node - node for authenticating other nodes | ||
777 | * @ch: common header | ||
778 | * @hmac: The HMAC | ||
779 | */ | ||
780 | struct ubifs_auth_node { | ||
781 | struct ubifs_ch ch; | ||
782 | __u8 hmac[]; | ||
783 | } __packed; | ||
784 | |||
785 | /** | ||
750 | * struct ubifs_branch - key/reference/length branch | 786 | * struct ubifs_branch - key/reference/length branch |
751 | * @lnum: LEB number of the target node | 787 | * @lnum: LEB number of the target node |
752 | * @offs: offset within @lnum | 788 | * @offs: offset within @lnum |
753 | * @len: target node length | 789 | * @len: target node length |
754 | * @key: key | 790 | * @key: key |
791 | * | ||
792 | * In an authenticated UBIFS we have the hash of the referenced node after @key. | ||
793 | * This can't be added to the struct type definition because @key is a | ||
794 | * dynamically sized element already. | ||
755 | */ | 795 | */ |
756 | struct ubifs_branch { | 796 | struct ubifs_branch { |
757 | __le32 lnum; | 797 | __le32 lnum; |