linux-mtd.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] mtd-utils: mkfs.ubifs: Add signing support for UBIFS images
@ 2019-08-06 10:49 Sascha Hauer
  2019-08-06 10:49 ` [PATCH 1/2] ubifs-media: Update to Linux-5.3-rc3 Sascha Hauer
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Sascha Hauer @ 2019-08-06 10:49 UTC (permalink / raw)
  To: linux-mtd; +Cc: Richard Weinberger, Sascha Hauer, david.oberhollenzer

This series adds the userspace part to mkfs.ubifs to generate signed UBIFS
images. With this a UBIFS image can be cryptographically signed in PKCS
#7 CMS format which is then authenticated in the Kernel before mounting
it. The necessary Kernel bits have been merged with 817aa094842d
("ubifs: support offline signed images").

Here is a quick walkthrough for generating and mounting a signed UBIFS image
using the kernel provided keys used for module signing:

- configure kernel with CONFIG_UBIFS_FS_AUTHENTICATION, CONFIG_MODULE_SIG and
  CONFIG_INTEGRITY_ASYMMETRIC_KEYS enabled (assumed to be in ~/linux/ in
  this example)
- build kernel, ~/linux/certs/signing_key.x509 and ~/linux/certs/signing_key.pem
  will be generated
- generate ubifs image:

  mkfs.ubifs --hash-algo=sha256 --auth-cert=~/linux/certs/signing_key.x509 \
	-d root -e  126976 -o ~/signed.ubifs -c 1024 -m 2048 \
	--auth-key=~/linux/certs/signing_key.pem

- flash UBIFS image onto target and mount:

  ubimkvol -N root -s 64MiB /dev/ubi0
  ubiupdatevol /dev/ubi0_0 signed.ubifs
  cat mysecret | keyctl padd logon ubifs:root @s
  mount -t ubifs /dev/ubi0_0 /mnt/ -o auth_hash_name=sha256,auth_key=ubifs:root


Sascha Hauer (2):
  ubifs-media: Update to Linux-5.3-rc3
  mkfs.ubifs: Add authentication support

 include/mtd/ubifs-media.h           |  75 ++++-
 ubifs-utils/Makemodule.am           |   3 +-
 ubifs-utils/mkfs.ubifs/lpt.c        |  12 +
 ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 172 +++++++++---
 ubifs-utils/mkfs.ubifs/mkfs.ubifs.h |   1 +
 ubifs-utils/mkfs.ubifs/sign.c       | 409 ++++++++++++++++++++++++++++
 ubifs-utils/mkfs.ubifs/sign.h       |  80 ++++++
 ubifs-utils/mkfs.ubifs/ubifs.h      |  22 +-
 8 files changed, 730 insertions(+), 44 deletions(-)
 create mode 100644 ubifs-utils/mkfs.ubifs/sign.c
 create mode 100644 ubifs-utils/mkfs.ubifs/sign.h

-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/2] ubifs-media: Update to Linux-5.3-rc3
  2019-08-06 10:49 [PATCH 0/2] mtd-utils: mkfs.ubifs: Add signing support for UBIFS images Sascha Hauer
@ 2019-08-06 10:49 ` Sascha Hauer
  2019-08-06 10:49 ` [PATCH 2/2] mkfs.ubifs: Add authentication support Sascha Hauer
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 10+ messages in thread
From: Sascha Hauer @ 2019-08-06 10:49 UTC (permalink / raw)
  To: linux-mtd; +Cc: Richard Weinberger, Sascha Hauer, david.oberhollenzer

This updates ubifs-media.h to Linux-5.3-rc3 which brings us the bits
and pieces necessary for UBIFS authentication and offline signing.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 include/mtd/ubifs-media.h | 75 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 70 insertions(+), 5 deletions(-)

diff --git a/include/mtd/ubifs-media.h b/include/mtd/ubifs-media.h
index 7751ac7..f1e3a14 100644
--- a/include/mtd/ubifs-media.h
+++ b/include/mtd/ubifs-media.h
@@ -288,6 +288,9 @@ enum {
 #define UBIFS_IDX_NODE_SZ  sizeof(struct ubifs_idx_node)
 #define UBIFS_CS_NODE_SZ   sizeof(struct ubifs_cs_node)
 #define UBIFS_ORPH_NODE_SZ sizeof(struct ubifs_orph_node)
+#define UBIFS_AUTH_NODE_SZ sizeof(struct ubifs_auth_node)
+#define UBIFS_SIG_NODE_SZ  sizeof(struct ubifs_sig_node)
+
 /* Extended attribute entry nodes are identical to directory entry nodes */
 #define UBIFS_XENT_NODE_SZ UBIFS_DENT_NODE_SZ
 /* Only this does not have to be multiple of 8 bytes */
@@ -302,12 +305,20 @@ enum {
 /* The largest UBIFS node */
 #define UBIFS_MAX_NODE_SZ UBIFS_MAX_INO_NODE_SZ
 
+/* The maxmimum size of a hash, enough for sha512 */
+#define UBIFS_MAX_HASH_LEN 64
+
+/* The maxmimum size of a hmac, enough for hmac(sha512) */
+#define UBIFS_MAX_HMAC_LEN 64
+
 /*
  * xattr name of UBIFS encryption context, we don't use a prefix
  * nor a long name to not waste space on the flash.
  */
 #define UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT "c"
 
+/* Type field in ubifs_sig_node */
+#define UBIFS_SIGNATURE_TYPE_PKCS7	1
 
 /*
  * On-flash inode flags.
@@ -369,6 +380,8 @@ enum {
  * UBIFS_IDX_NODE: index node
  * UBIFS_CS_NODE: commit start node
  * UBIFS_ORPH_NODE: orphan node
+ * UBIFS_AUTH_NODE: authentication node
+ * UBIFS_SIG_NODE: signature node
  * UBIFS_NODE_TYPES_CNT: count of supported node types
  *
  * Note, we index arrays by these numbers, so keep them low and contiguous.
@@ -388,6 +401,8 @@ enum {
 	UBIFS_IDX_NODE,
 	UBIFS_CS_NODE,
 	UBIFS_ORPH_NODE,
+	UBIFS_AUTH_NODE,
+	UBIFS_SIG_NODE,
 	UBIFS_NODE_TYPES_CNT,
 };
 
@@ -425,15 +440,19 @@ enum {
  * UBIFS_FLG_DOUBLE_HASH: store a 32bit cookie in directory entry nodes to
  *			  support 64bit cookies for lookups by hash
  * UBIFS_FLG_ENCRYPTION: this filesystem contains encrypted files
+ * UBIFS_FLG_AUTHENTICATION: this filesystem contains hashes for authentication
  */
 enum {
 	UBIFS_FLG_BIGLPT = 0x02,
 	UBIFS_FLG_SPACE_FIXUP = 0x04,
 	UBIFS_FLG_DOUBLE_HASH = 0x08,
 	UBIFS_FLG_ENCRYPTION = 0x10,
+	UBIFS_FLG_AUTHENTICATION = 0x20,
 };
 
-#define UBIFS_FLG_MASK (UBIFS_FLG_BIGLPT|UBIFS_FLG_SPACE_FIXUP|UBIFS_FLG_DOUBLE_HASH|UBIFS_FLG_ENCRYPTION)
+#define UBIFS_FLG_MASK (UBIFS_FLG_BIGLPT | UBIFS_FLG_SPACE_FIXUP | \
+		UBIFS_FLG_DOUBLE_HASH | UBIFS_FLG_ENCRYPTION | \
+		UBIFS_FLG_AUTHENTICATION)
 
 /**
  * struct ubifs_ch - common header node.
@@ -568,8 +587,6 @@ struct ubifs_dent_node {
  * @compr_size: compressed data size in bytes, only valid when data is encrypted
  * @data: data
  *
- * Note, do not forget to amend 'zero_data_node_unused()' function when
- * changing the padding fields.
  */
 struct ubifs_data_node {
 	struct ubifs_ch ch;
@@ -639,6 +656,12 @@ struct ubifs_pad_node {
  * @time_gran: time granularity in nanoseconds
  * @uuid: UUID generated when the file system image was created
  * @ro_compat_version: UBIFS R/O compatibility version
+ * @hmac: HMAC to authenticate the superblock node
+ * @hmac_wkm: HMAC of a well known message (the string "UBIFS") as a convenience
+ *            to the user to check if the correct key is passed.
+ * @hash_algo: The hash algo used for this filesystem (one of enum hash_algo)
+ * @hash_mst: hash of the master node, only valid for signed images in which the
+ *            master node does not contain a hmac
  */
 struct ubifs_sb_node {
 	struct ubifs_ch ch;
@@ -665,7 +688,12 @@ struct ubifs_sb_node {
 	__le64 rp_size;
 	__le32 time_gran;
 	__u8 uuid[16];
-	__u8 padding2[3972];
+	__le32 ro_compat_version;
+	__u8 hmac[UBIFS_MAX_HMAC_LEN];
+	__u8 hmac_wkm[UBIFS_MAX_HMAC_LEN];
+	__le16 hash_algo;
+	__u8 hash_mst[UBIFS_MAX_HASH_LEN];
+	__u8 padding2[3774];
 } __attribute__ ((packed));
 
 /**
@@ -700,6 +728,9 @@ struct ubifs_sb_node {
  * @empty_lebs: number of empty logical eraseblocks
  * @idx_lebs: number of indexing logical eraseblocks
  * @leb_cnt: count of LEBs used by file-system
+ * @hash_root_idx: the hash of the root index node
+ * @hash_lpt: the hash of the LPT
+ * @hmac: HMAC to authenticate the master node
  * @padding: reserved for future, zeroes
  */
 struct ubifs_mst_node {
@@ -732,7 +763,10 @@ struct ubifs_mst_node {
 	__le32 empty_lebs;
 	__le32 idx_lebs;
 	__le32 leb_cnt;
-	__u8 padding[344];
+	__u8 hash_root_idx[UBIFS_MAX_HASH_LEN];
+	__u8 hash_lpt[UBIFS_MAX_HASH_LEN];
+	__u8 hmac[UBIFS_MAX_HMAC_LEN];
+	__u8 padding[152];
 } __attribute__ ((packed));
 
 /**
@@ -751,12 +785,43 @@ struct ubifs_ref_node {
 	__u8 padding[28];
 } __attribute__ ((packed));
 
+/**
+ * struct ubifs_auth_node - node for authenticating other nodes
+ * @ch: common header
+ * @hmac: The HMAC
+ */
+struct ubifs_auth_node {
+	struct ubifs_ch ch;
+	__u8 hmac[];
+} __attribute__ ((packed));
+
+/**
+ * struct ubifs_sig_node - node for signing other nodes
+ * @ch: common header
+ * @type: type of the signature, currently only UBIFS_SIGNATURE_TYPE_PKCS7
+ * supported
+ * @len: The length of the signature data
+ * @padding: reserved for future, zeroes
+ * @sig: The signature data
+ */
+struct ubifs_sig_node {
+	struct ubifs_ch ch;
+	__le32 type;
+	__le32 len;
+	__u8 padding[32];
+	__u8 sig[];
+} __attribute__ ((packed));
+
 /**
  * struct ubifs_branch - key/reference/length branch
  * @lnum: LEB number of the target node
  * @offs: offset within @lnum
  * @len: target node length
  * @key: key
+ *
+ * In an authenticated UBIFS we have the hash of the referenced node after @key.
+ * This can't be added to the struct type definition because @key is a
+ * dynamically sized element already.
  */
 struct ubifs_branch {
 	__le32 lnum;
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/2] mkfs.ubifs: Add authentication support
  2019-08-06 10:49 [PATCH 0/2] mtd-utils: mkfs.ubifs: Add signing support for UBIFS images Sascha Hauer
  2019-08-06 10:49 ` [PATCH 1/2] ubifs-media: Update to Linux-5.3-rc3 Sascha Hauer
@ 2019-08-06 10:49 ` Sascha Hauer
  2019-08-19  7:29 ` [PATCH 0/2] mtd-utils: mkfs.ubifs: Add signing support for UBIFS images David Oberhollenzer
  2020-02-07 15:25 ` Kevin Raymond
  3 siblings, 0 replies; 10+ messages in thread
From: Sascha Hauer @ 2019-08-06 10:49 UTC (permalink / raw)
  To: linux-mtd; +Cc: Richard Weinberger, Sascha Hauer, david.oberhollenzer

This adds support for authenticated UBIFS images. In authenticated
images all UBIFS nodes are hashed as described in the UBIFS
authentication whitepaper. Additionally the superblock node contains a
hash of the master node and itself is cryptographically signed in a node
following the superblock node. The signature is in PKCS #7 CMS format.

To generate an authenticated image these options are necessary:

--hash-algo=NAME     hash algorithm to use for signed images
                     (Valid options include sha1, sha256, sha512)
--auth-key=FILE      filename or PKCS #11 uri containing the authentication key
                     for signing
--auth-cert=FILE     Authentication certificate filename for signing. Unused
                     when certificate is provided via PKCS #11

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 ubifs-utils/Makemodule.am           |   3 +-
 ubifs-utils/mkfs.ubifs/lpt.c        |  12 +
 ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 172 +++++++++---
 ubifs-utils/mkfs.ubifs/mkfs.ubifs.h |   1 +
 ubifs-utils/mkfs.ubifs/sign.c       | 409 ++++++++++++++++++++++++++++
 ubifs-utils/mkfs.ubifs/sign.h       |  80 ++++++
 ubifs-utils/mkfs.ubifs/ubifs.h      |  22 +-
 7 files changed, 660 insertions(+), 39 deletions(-)
 create mode 100644 ubifs-utils/mkfs.ubifs/sign.c
 create mode 100644 ubifs-utils/mkfs.ubifs/sign.h

diff --git a/ubifs-utils/Makemodule.am b/ubifs-utils/Makemodule.am
index 164ce09..0c64445 100644
--- a/ubifs-utils/Makemodule.am
+++ b/ubifs-utils/Makemodule.am
@@ -19,7 +19,8 @@ mkfs_ubifs_SOURCES = \
 
 if WITH_CRYPTO
 mkfs_ubifs_SOURCES += ubifs-utils/mkfs.ubifs/crypto.c \
-		ubifs-utils/mkfs.ubifs/fscrypt.c
+		ubifs-utils/mkfs.ubifs/fscrypt.c \
+		ubifs-utils/mkfs.ubifs/sign.c
 endif
 
 mkfs_ubifs_LDADD = libmtd.a libubi.a $(ZLIB_LIBS) $(LZO_LIBS) $(ZSTD_LIBS) $(UUID_LIBS) $(LIBSELINUX_LIBS) $(OPENSSL_LIBS) -lm
diff --git a/ubifs-utils/mkfs.ubifs/lpt.c b/ubifs-utils/mkfs.ubifs/lpt.c
index 6aa0b88..7ee739a 100644
--- a/ubifs-utils/mkfs.ubifs/lpt.c
+++ b/ubifs-utils/mkfs.ubifs/lpt.c
@@ -22,6 +22,10 @@
 
 #include "mkfs.ubifs.h"
 
+#ifdef WITH_CRYPTO
+#include <openssl/evp.h>
+#endif
+
 /**
  * do_calc_lpt_geom - calculate sizes for the LPT area.
  * @c: the UBIFS file-system description object
@@ -374,6 +378,7 @@ int create_lpt(struct ubifs_info *c)
 	struct ubifs_nnode *nnode = NULL;
 	void *buf = NULL, *p;
 	int *lsave = NULL;
+	unsigned int md_len;
 
 	pnode = malloc(sizeof(struct ubifs_pnode));
 	nnode = malloc(sizeof(struct ubifs_nnode));
@@ -386,6 +391,8 @@ int create_lpt(struct ubifs_info *c)
 	memset(pnode, 0 , sizeof(struct ubifs_pnode));
 	memset(nnode, 0 , sizeof(struct ubifs_nnode));
 
+	hash_digest_init();
+
 	c->lscan_lnum = c->main_first;
 
 	lnum = c->lpt_first;
@@ -429,6 +436,9 @@ int create_lpt(struct ubifs_info *c)
 			}
 		}
 		pack_pnode(c, p, pnode);
+
+		hash_digest_update(p, c->pnode_sz);
+
 		p += c->pnode_sz;
 		len += c->pnode_sz;
 		/*
@@ -439,6 +449,8 @@ int create_lpt(struct ubifs_info *c)
 		pnode->num += 1;
 	}
 
+	hash_digest_final(c->lpt_hash, &md_len);
+
 	row = c->lpt_hght - 1;
 	/* Add all nnodes, one level at a time */
 	while (1) {
diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index 58ebf8c..5748aaa 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -68,6 +68,7 @@ static char *secontext;
  * @lnum: LEB number
  * @offs: offset
  * @len: length
+ * @hash: hash of the node
  *
  * The index is recorded as a linked list which is sorted and used to create
  * the bottom level of the on-flash index tree. The remaining levels of the
@@ -82,6 +83,7 @@ struct idx_entry {
 	int lnum;
 	int offs;
 	int len;
+	uint8_t hash[UBIFS_MAX_HASH_LEN];
 };
 
 /**
@@ -164,6 +166,12 @@ static unsigned long long creat_sqnum;
 
 static const char *optstring = "d:r:m:o:D:yh?vVe:c:g:f:Fp:k:x:X:j:R:l:j:UQqaK:b:P:C:";
 
+enum {
+	HASH_ALGO_OPTION = CHAR_MAX + 1,
+	AUTH_KEY_OPTION,
+	AUTH_CERT_OPTION,
+};
+
 static const struct option longopts[] = {
 	{"root",               1, NULL, 'r'},
 	{"min-io-size",        1, NULL, 'm'},
@@ -192,6 +200,9 @@ static const struct option longopts[] = {
 	{"key-descriptor",     1, NULL, 'b'},
 	{"padding",            1, NULL, 'P'},
 	{"cipher",             1, NULL, 'C'},
+	{"hash-algo",          1, NULL, HASH_ALGO_OPTION},
+	{"auth-key",           1, NULL, AUTH_KEY_OPTION},
+	{"auth-cert",          1, NULL, AUTH_CERT_OPTION},
 	{NULL, 0, NULL, 0}
 };
 
@@ -242,6 +253,12 @@ static const char *helptext =
 "                         (default = 4).\n"
 "-C, --cipher=NAME        Specify cipher to use for file level encryption\n"
 "                         (default is \"AES-256-XTS\").\n"
+"    --hash-algo=NAME     hash algorithm to use for signed images\n"
+"                         (Valid options include sha1, sha256, sha512)\n"
+"    --auth-key=FILE      filename or PKCS #11 uri containing the authentication key\n"
+"                         for signing\n"
+"    --auth-cert=FILE     Authentication certificate filename for signing. Unused\n"
+"                         when certificate is provided via PKCS #11\n"
 "-h, --help               display this help text\n\n"
 "Note, SIZE is specified in bytes, but it may also be specified in Kilobytes,\n"
 "Megabytes, and Gigabytes if a KiB, MiB, or GiB suffix is used.\n\n"
@@ -261,7 +278,15 @@ static const char *helptext =
 "when flashing the image and the second time when UBIFS is mounted and writes useful\n"
 "data there. A proper UBI-aware flasher should skip such NAND pages, though. Note, this\n"
 "flag may make the first mount very slow, because the \"free space fixup\" procedure\n"
-"takes time. This feature is supported by the Linux kernel starting from version 3.0.\n";
+"takes time. This feature is supported by the Linux kernel starting from version 3.0.\n"
+"\n"
+"mkfs.ubifs supports building signed images. For this the \"--hash-algo\",\n"
+"\"--auth-key\" and \"--auth-cert\" options have to be specified.\n";
+
+static inline uint8_t *ubifs_branch_hash(struct ubifs_branch *br)
+{
+	return (void *)br + sizeof(*br) + c->key_len;
+}
 
 /**
  * make_path - make a path name from a directory and a name.
@@ -753,14 +778,27 @@ static int get_options(int argc, char**argv)
 			}
 			break;
 		}
-		case 'C':
 #ifdef WITH_CRYPTO
+		case 'C':
 			cipher_name = optarg;
+			break;
+		case HASH_ALGO_OPTION:
+			c->hash_algo_name = xstrdup(optarg);
+			break;
+		case AUTH_KEY_OPTION:
+			c->auth_key_filename = xstrdup(optarg);
+			break;
+		case AUTH_CERT_OPTION:
+			c->auth_cert_filename = xstrdup(optarg);
+			break;
+		}
 #else
+		case 'C':
+		case HASH_ALGO_OPTION:
+		case AUTH_KEY_OPTION:
+		case X509_OPTION:
 			return err_msg("mkfs.ubifs was built without crypto support.");
 #endif
-			break;
-		}
 	}
 
 	if (optind != argc && !output)
@@ -1063,9 +1101,10 @@ static void set_lprops(int lnum, int offs, int flags)
  * @lnum: node LEB number
  * @offs: node offset
  * @len: node length
+ * @hash: hash of the node
  */
 static int add_to_index(union ubifs_key *key, char *name, int name_len,
-			int lnum, int offs, int len)
+			int lnum, int offs, int len, const uint8_t *hash)
 {
 	struct idx_entry *e;
 
@@ -1079,6 +1118,8 @@ static int add_to_index(union ubifs_key *key, char *name, int name_len,
 	e->lnum = lnum;
 	e->offs = offs;
 	e->len = len;
+	memcpy(e->hash, hash, c->hash_len);
+
 	if (!idx_list_first)
 		idx_list_first = e;
 	if (idx_list_last)
@@ -1137,6 +1178,7 @@ static int reserve_space(int len, int *lnum, int *offs)
 static int add_node(union ubifs_key *key, char *name, int name_len, void *node, int len)
 {
 	int err, lnum, offs, type = key_type(key);
+	uint8_t hash[UBIFS_MAX_HASH_LEN];
 
 	if (type == UBIFS_DENT_KEY || type == UBIFS_XENT_KEY) {
 		if (!name)
@@ -1156,7 +1198,9 @@ static int add_node(union ubifs_key *key, char *name, int name_len, void *node,
 	memcpy(leb_buf + offs, node, len);
 	memset(leb_buf + offs + len, 0xff, ALIGN(len, 8) - len);
 
-	add_to_index(key, name, name_len, lnum, offs, len);
+	ubifs_node_calc_hash(node, hash);
+
+	add_to_index(key, name, name_len, lnum, offs, len, hash);
 
 	return 0;
 }
@@ -2298,6 +2342,7 @@ static int write_index(void)
 	struct ubifs_idx_node *idx;
 	struct ubifs_branch *br;
 	int child_cnt = 0, j, level, blnum, boffs, blen, blast_len, err;
+	uint8_t *hashes;
 
 	dbg_msg(1, "leaf node count: %zd", idx_cnt);
 
@@ -2321,6 +2366,9 @@ static int write_index(void)
 	cnt = idx_cnt / c->fanout;
 	if (idx_cnt % c->fanout)
 		cnt += 1;
+
+	hashes = xmalloc(c->hash_len * cnt);
+
 	p = idx_ptr;
 	blnum = head_lnum;
 	boffs = head_offs;
@@ -2345,8 +2393,11 @@ static int write_index(void)
 			br->lnum = cpu_to_le32((*p)->lnum);
 			br->offs = cpu_to_le32((*p)->offs);
 			br->len = cpu_to_le32((*p)->len);
+			memcpy(ubifs_branch_hash(br), (*p)->hash, c->hash_len);
 		}
 		add_idx_node(idx, child_cnt);
+
+		ubifs_node_calc_hash(idx, hashes + i * c->hash_len);
 	}
 	/* Write level 1 index nodes and above */
 	level = 0;
@@ -2423,11 +2474,18 @@ static int write_index(void)
 				 */
 				boffs += ALIGN(blen, 8);
 				p += pstep;
+
+				memcpy(ubifs_branch_hash(br),
+				       hashes + bn * c->hash_len,
+				       c->hash_len);
 			}
 			add_idx_node(idx, child_cnt);
+			ubifs_node_calc_hash(idx, hashes + i * c->hash_len);
 		}
 	}
 
+	memcpy(c->root_idx_hash, hashes, c->hash_len);
+
 	/* Free stuff */
 	for (i = 0; i < idx_cnt; i++) {
 		free(idx_ptr[i]->name);
@@ -2512,44 +2570,75 @@ static int ubifs_format_version(void)
  */
 static int write_super(void)
 {
-	struct ubifs_sb_node sup;
-
-	memset(&sup, 0, UBIFS_SB_NODE_SZ);
-
-	sup.ch.node_type  = UBIFS_SB_NODE;
-	sup.key_hash      = c->key_hash_type;
-	sup.min_io_size   = cpu_to_le32(c->min_io_size);
-	sup.leb_size      = cpu_to_le32(c->leb_size);
-	sup.leb_cnt       = cpu_to_le32(c->leb_cnt);
-	sup.max_leb_cnt   = cpu_to_le32(c->max_leb_cnt);
-	sup.max_bud_bytes = cpu_to_le64(c->max_bud_bytes);
-	sup.log_lebs      = cpu_to_le32(c->log_lebs);
-	sup.lpt_lebs      = cpu_to_le32(c->lpt_lebs);
-	sup.orph_lebs     = cpu_to_le32(c->orph_lebs);
-	sup.jhead_cnt     = cpu_to_le32(c->jhead_cnt);
-	sup.fanout        = cpu_to_le32(c->fanout);
-	sup.lsave_cnt     = cpu_to_le32(c->lsave_cnt);
-	sup.fmt_version   = cpu_to_le32(ubifs_format_version());
-	sup.default_compr = cpu_to_le16(c->default_compr);
-	sup.rp_size       = cpu_to_le64(c->rp_size);
-	sup.time_gran     = cpu_to_le32(DEFAULT_TIME_GRAN);
-	uuid_generate_random(sup.uuid);
+	void *buf;
+	struct ubifs_sb_node *sup;
+	struct ubifs_sig_node *sig;
+	int err, len;
+
+	buf = xzalloc(c->leb_size);
+
+	sup = buf;
+	sig = buf + UBIFS_SB_NODE_SZ;
+
+	sup->ch.node_type  = UBIFS_SB_NODE;
+	sup->key_hash      = c->key_hash_type;
+	sup->min_io_size   = cpu_to_le32(c->min_io_size);
+	sup->leb_size      = cpu_to_le32(c->leb_size);
+	sup->leb_cnt       = cpu_to_le32(c->leb_cnt);
+	sup->max_leb_cnt   = cpu_to_le32(c->max_leb_cnt);
+	sup->max_bud_bytes = cpu_to_le64(c->max_bud_bytes);
+	sup->log_lebs      = cpu_to_le32(c->log_lebs);
+	sup->lpt_lebs      = cpu_to_le32(c->lpt_lebs);
+	sup->orph_lebs     = cpu_to_le32(c->orph_lebs);
+	sup->jhead_cnt     = cpu_to_le32(c->jhead_cnt);
+	sup->fanout        = cpu_to_le32(c->fanout);
+	sup->lsave_cnt     = cpu_to_le32(c->lsave_cnt);
+	sup->fmt_version   = cpu_to_le32(ubifs_format_version());
+	sup->default_compr = cpu_to_le16(c->default_compr);
+	sup->rp_size       = cpu_to_le64(c->rp_size);
+	sup->time_gran     = cpu_to_le32(DEFAULT_TIME_GRAN);
+	sup->hash_algo     = cpu_to_le16(c->hash_algo);
+	uuid_generate_random(sup->uuid);
+
 	if (verbose) {
 		char s[40];
 
-		uuid_unparse_upper(sup.uuid, s);
+		uuid_unparse_upper(sup->uuid, s);
 		printf("\tUUID:         %s\n", s);
 	}
 	if (c->big_lpt)
-		sup.flags |= cpu_to_le32(UBIFS_FLG_BIGLPT);
+		sup->flags |= cpu_to_le32(UBIFS_FLG_BIGLPT);
 	if (c->space_fixup)
-		sup.flags |= cpu_to_le32(UBIFS_FLG_SPACE_FIXUP);
+		sup->flags |= cpu_to_le32(UBIFS_FLG_SPACE_FIXUP);
 	if (c->double_hash)
-		sup.flags |= cpu_to_le32(UBIFS_FLG_DOUBLE_HASH);
+		sup->flags |= cpu_to_le32(UBIFS_FLG_DOUBLE_HASH);
 	if (c->encrypted)
-		sup.flags |= cpu_to_le32(UBIFS_FLG_ENCRYPTION);
+		sup->flags |= cpu_to_le32(UBIFS_FLG_ENCRYPTION);
+	if (authenticated()) {
+		sup->flags |= cpu_to_le32(UBIFS_FLG_AUTHENTICATION);
+		memcpy(sup->hash_mst, c->mst_hash, c->hash_len);
+	}
 
-	return write_node(&sup, UBIFS_SB_NODE_SZ, UBIFS_SB_LNUM);
+	prepare_node(sup, UBIFS_SB_NODE_SZ);
+
+	err = sign_superblock_node(sup);
+	if (err)
+		goto out;
+
+	sig = (void *)(sup + 1);
+	prepare_node(sig, UBIFS_SIG_NODE_SZ + le32_to_cpu(sig->len));
+
+	len = do_pad(sig, UBIFS_SIG_NODE_SZ + le32_to_cpu(sig->len));
+
+	err = write_leb(UBIFS_SB_LNUM, UBIFS_SB_NODE_SZ + len, sup);
+	if (err)
+		goto out;
+
+	err = 0;
+out:
+	free(buf);
+
+	return err;
 }
 
 /**
@@ -2592,6 +2681,11 @@ static int write_master(void)
 	mst.total_dark   = cpu_to_le64(c->lst.total_dark);
 	mst.leb_cnt      = cpu_to_le32(c->leb_cnt);
 
+	if (authenticated()) {
+		memcpy(mst.hash_root_idx, c->root_idx_hash, c->hash_len);
+		memcpy(mst.hash_lpt, c->lpt_hash, c->hash_len);
+	}
+
 	err = write_node(&mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM);
 	if (err)
 		return err;
@@ -2600,6 +2694,8 @@ static int write_master(void)
 	if (err)
 		return err;
 
+	mst_node_calc_hash(&mst, c->mst_hash);
+
 	return 0;
 }
 
@@ -2864,6 +2960,10 @@ static int mkfs(void)
 	if (err)
 		goto out;
 
+	err = init_authentication();
+	if (err)
+		goto out;
+
 	err = write_data();
 	if (err)
 		goto out;
@@ -2884,11 +2984,11 @@ static int mkfs(void)
 	if (err)
 		goto out;
 
-	err = write_super();
+	err = write_master();
 	if (err)
 		goto out;
 
-	err = write_master();
+	err = write_super();
 	if (err)
 		goto out;
 
diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.h b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.h
index f1425c5..5690984 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.h
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.h
@@ -63,6 +63,7 @@
 #include "key.h"
 #include "lpt.h"
 #include "compr.h"
+#include "sign.h"
 
 /*
  * Compression flags are duplicated so that compr.c can compile without ubifs.h.
diff --git a/ubifs-utils/mkfs.ubifs/sign.c b/ubifs-utils/mkfs.ubifs/sign.c
new file mode 100644
index 0000000..b7ad7ef
--- /dev/null
+++ b/ubifs-utils/mkfs.ubifs/sign.c
@@ -0,0 +1,409 @@
+/*
+ * Copyright (C) 2018 Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Sascha Hauer
+ */
+
+#include "mkfs.ubifs.h"
+#include "common.h"
+
+#include <openssl/evp.h>
+#include <openssl/opensslv.h>
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/engine.h>
+#include <openssl/cms.h>
+#include <openssl/conf.h>
+#include <err.h>
+
+static struct ubifs_info *c = &info_;
+
+EVP_MD_CTX *hash_md;
+const EVP_MD *md;
+
+int authenticated(void)
+{
+	return c->hash_algo_name != NULL;
+}
+
+static int match_string(const char * const *array, size_t n, const char *string)
+{
+	int index;
+	const char *item;
+
+	for (index = 0; index < n; index++) {
+		item = array[index];
+		if (!item)
+			break;
+		if (!strcmp(item, string))
+			return index;
+	}
+
+	return -EINVAL;
+}
+
+#include <linux/hash_info.h>
+
+const char *const hash_algo_name[HASH_ALGO__LAST] = {
+	[HASH_ALGO_MD4]		= "md4",
+	[HASH_ALGO_MD5]		= "md5",
+	[HASH_ALGO_SHA1]	= "sha1",
+	[HASH_ALGO_RIPE_MD_160]	= "rmd160",
+	[HASH_ALGO_SHA256]	= "sha256",
+	[HASH_ALGO_SHA384]	= "sha384",
+	[HASH_ALGO_SHA512]	= "sha512",
+	[HASH_ALGO_SHA224]	= "sha224",
+	[HASH_ALGO_RIPE_MD_128]	= "rmd128",
+	[HASH_ALGO_RIPE_MD_256]	= "rmd256",
+	[HASH_ALGO_RIPE_MD_320]	= "rmd320",
+	[HASH_ALGO_WP_256]	= "wp256",
+	[HASH_ALGO_WP_384]	= "wp384",
+	[HASH_ALGO_WP_512]	= "wp512",
+	[HASH_ALGO_TGR_128]	= "tgr128",
+	[HASH_ALGO_TGR_160]	= "tgr160",
+	[HASH_ALGO_TGR_192]	= "tgr192",
+	[HASH_ALGO_SM3_256]	= "sm3-256",
+};
+
+static void display_openssl_errors(int l)
+{
+	const char *file;
+	char buf[120];
+	int e, line;
+
+	if (ERR_peek_error() == 0)
+		return;
+	fprintf(stderr, "At main.c:%d:\n", l);
+
+	while ((e = ERR_get_error_line(&file, &line))) {
+		ERR_error_string(e, buf);
+		fprintf(stderr, "- SSL %s: %s:%d\n", buf, file, line);
+	}
+}
+
+static void drain_openssl_errors(void)
+{
+	const char *file;
+	int line;
+
+	if (ERR_peek_error() == 0)
+		return;
+	while (ERR_get_error_line(&file, &line)) {}
+}
+
+#define ssl_err_msg(fmt, ...) ({			\
+	display_openssl_errors(__LINE__);		\
+	err_msg(fmt, ## __VA_ARGS__);			\
+	-1;						\
+})
+
+static const char *key_pass;
+
+static int pem_pw_cb(char *buf, int len, __attribute__((unused)) int w,
+		     __attribute__((unused)) void *v)
+{
+	int pwlen;
+
+	if (!key_pass)
+		return -1;
+
+	pwlen = strlen(key_pass);
+	if (pwlen >= len)
+		return -1;
+
+	strcpy(buf, key_pass);
+
+	/* If it's wrong, don't keep trying it. */
+	key_pass = NULL;
+
+	return pwlen;
+}
+
+static EVP_PKEY *read_private_key(const char *private_key_name, X509 **cert)
+{
+	EVP_PKEY *private_key = NULL;
+	int err;
+
+	*cert = NULL;
+
+	if (!strncmp(private_key_name, "pkcs11:", 7)) {
+		ENGINE *e;
+		struct {
+			const char *url;
+			X509 *cert;
+		} parms = {
+			.url = private_key_name,
+		};
+
+		ENGINE_load_builtin_engines();
+		drain_openssl_errors();
+		e = ENGINE_by_id("pkcs11");
+		if (!e) {
+			ssl_err_msg("Load PKCS#11 ENGINE");
+			return NULL;
+		}
+
+		if (ENGINE_init(e)) {
+			drain_openssl_errors();
+		} else {
+			ssl_err_msg("ENGINE_init");
+			return NULL;
+		}
+
+		if (key_pass)
+			if (!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0)) {
+				ssl_err_msg("Set PKCS#11 PIN");
+				return NULL;
+			}
+
+		private_key = ENGINE_load_private_key(e, private_key_name,
+						      NULL, NULL);
+
+		err = ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, &parms, NULL, 0);
+		if (!err || !parms.cert) {
+			ssl_err_msg("Load certificate");
+		}
+		*cert = parms.cert;
+		fprintf(stderr, "Using cert %p\n", *cert);
+	} else {
+		BIO *b;
+
+		b = BIO_new_file(private_key_name, "rb");
+		if (!b)
+			goto out;
+
+		private_key = PEM_read_bio_PrivateKey(b, NULL, pem_pw_cb,
+						      NULL);
+		BIO_free(b);
+	}
+out:
+	if (!private_key)
+		ssl_err_msg("failed opening private key %s", private_key_name);
+
+	return private_key;
+}
+
+static X509 *read_x509(const char *x509_name)
+{
+	unsigned char buf[2];
+	X509 *x509 = NULL;
+	BIO *b;
+	int n;
+
+	b = BIO_new_file(x509_name, "rb");
+	if (!b)
+		goto out;
+
+	/* Look at the first two bytes of the file to determine the encoding */
+	n = BIO_read(b, buf, 2);
+	if (n != 2) {
+		if (BIO_should_retry(b))
+			err_msg("%s: Read wanted retry", x509_name);
+		if (n >= 0)
+			err_msg("%s: Short read", x509_name);
+		goto out;
+	}
+
+	if (BIO_reset(b))
+		goto out;
+
+	if (buf[0] == 0x30 && buf[1] >= 0x81 && buf[1] <= 0x84)
+		/* Assume raw DER encoded X.509 */
+		x509 = d2i_X509_bio(b, NULL);
+	else
+		/* Assume PEM encoded X.509 */
+		x509 = PEM_read_bio_X509(b, NULL, NULL, NULL);
+
+	BIO_free(b);
+
+out:
+	if (!x509) {
+		ssl_err_msg("%s", x509_name);
+		return NULL;
+	}
+
+	return x509;
+}
+
+int sign_superblock_node(void *node)
+{
+	EVP_PKEY *private_key;
+	CMS_ContentInfo *cms = NULL;
+	X509 *cert = NULL;
+	BIO *bd, *bm;
+	void *obuf;
+	long len;
+	int ret;
+	void *pret;
+	struct ubifs_sig_node *sig = node + UBIFS_SB_NODE_SZ;
+
+	if (!authenticated())
+		return 0;
+
+	ERR_load_crypto_strings();
+	ERR_clear_error();
+
+	key_pass = getenv("MKFS_UBIFS_SIGN_PIN");
+
+	bm = BIO_new_mem_buf(node, UBIFS_SB_NODE_SZ);
+
+	private_key = read_private_key(c->auth_key_filename, &cert);
+	if (!private_key)
+		return -1;
+
+	if (!cert) {
+		if (!c->auth_cert_filename)
+			return err_msg("authentication certificate not provided (--auth-cert)");
+		cert = read_x509(c->auth_cert_filename);
+	}
+
+	if (!cert)
+		return -1;
+
+	OpenSSL_add_all_digests();
+	display_openssl_errors(__LINE__);
+
+	cms = CMS_sign(NULL, NULL, NULL, NULL,
+		       CMS_NOCERTS | CMS_PARTIAL | CMS_BINARY |
+		       CMS_DETACHED | CMS_STREAM);
+	if (!cms)
+		return err_msg("CMS_sign failed");
+
+	pret = CMS_add1_signer(cms, cert, private_key, md,
+			      CMS_NOCERTS | CMS_BINARY |
+			      CMS_NOSMIMECAP | CMS_NOATTR);
+	if (!pret)
+		return err_msg("CMS_add1_signer failed");
+
+	ret = CMS_final(cms, bm, NULL, CMS_NOCERTS | CMS_BINARY);
+	if (!ret)
+		return err_msg("CMS_final failed");
+
+	bd = BIO_new(BIO_s_mem());
+
+	ret = i2d_CMS_bio_stream(bd, cms, NULL, 0);
+	if (!ret)
+		return err_msg("i2d_CMS_bio_stream failed");
+
+	len = BIO_get_mem_data(bd, &obuf);
+
+	sig->type = UBIFS_SIGNATURE_TYPE_PKCS7;
+	sig->len = cpu_to_le32(len);
+	sig->ch.node_type  = UBIFS_SIG_NODE;
+
+	memcpy(sig + 1, obuf, len);
+
+	BIO_free(bd);
+	BIO_free(bm);
+
+	return 0;
+}
+
+/**
+ * ubifs_node_calc_hash - calculate the hash of a UBIFS node
+ * @c: UBIFS file-system description object
+ * @node: the node to calculate a hash for
+ * @hash: the returned hash
+ */
+void ubifs_node_calc_hash(const void *node, uint8_t *hash)
+{
+	const struct ubifs_ch *ch = node;
+	unsigned int md_len;
+
+	if (!authenticated())
+		return;
+
+	EVP_DigestInit_ex(hash_md, md, NULL);
+	EVP_DigestUpdate(hash_md, node, le32_to_cpu(ch->len));
+	EVP_DigestFinal_ex(hash_md, hash, &md_len);
+}
+
+/**
+ * mst_node_calc_hash - calculate the hash of a UBIFS master node
+ * @c: UBIFS file-system description object
+ * @node: the node to calculate a hash for
+ * @hash: the returned hash
+ */
+void mst_node_calc_hash(const void *node, uint8_t *hash)
+{
+	unsigned int md_len;
+
+	if (!authenticated())
+		return;
+
+	EVP_DigestInit_ex(hash_md, md, NULL);
+	EVP_DigestUpdate(hash_md, node + sizeof(struct ubifs_ch),
+			 UBIFS_MST_NODE_SZ - sizeof(struct ubifs_ch));
+	EVP_DigestFinal_ex(hash_md, hash, &md_len);
+}
+
+void hash_digest_init(void)
+{
+	if (!authenticated())
+		return;
+
+	EVP_DigestInit_ex(hash_md, md, NULL);
+}
+
+void hash_digest_update(const void *buf, int len)
+{
+	if (!authenticated())
+		return;
+
+	EVP_DigestUpdate(hash_md, buf, len);
+}
+
+void hash_digest_final(void *hash, unsigned int *len)
+{
+	if (!authenticated())
+		return;
+
+	EVP_DigestFinal_ex(hash_md, hash, len);
+}
+
+int init_authentication(void)
+{
+	int hash_algo;
+
+	if (!c->auth_key_filename && !c->auth_cert_filename && !c->hash_algo_name)
+		return 0;
+
+	if (!c->auth_key_filename)
+		return err_msg("authentication key not given (--auth-key)");
+
+	if (!c->hash_algo_name)
+		return err_msg("Hash algorithm not given (--hash-algo)");
+
+	OPENSSL_no_config();
+	OpenSSL_add_all_algorithms();
+	ERR_load_crypto_strings();
+
+	md = EVP_get_digestbyname(c->hash_algo_name);
+	if (!md)
+		return err_msg("Unknown message digest %s", c->hash_algo_name);
+
+	hash_md = EVP_MD_CTX_create();
+	c->hash_len = EVP_MD_size(md);
+
+	hash_algo = match_string(hash_algo_name, HASH_ALGO__LAST, c->hash_algo_name);
+	if (hash_algo < 0)
+		return err_msg("Unsupported message digest %s", c->hash_algo_name);
+
+	c->hash_algo = hash_algo;
+
+	return 0;
+}
diff --git a/ubifs-utils/mkfs.ubifs/sign.h b/ubifs-utils/mkfs.ubifs/sign.h
new file mode 100644
index 0000000..fe9fdd8
--- /dev/null
+++ b/ubifs-utils/mkfs.ubifs/sign.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2018 Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Sascha Hauer
+ */
+
+#ifndef __UBIFS_SIGN_H__
+#define __UBIFS_SIGN_H__
+
+#ifdef WITH_CRYPTO
+#include <openssl/evp.h>
+
+void ubifs_node_calc_hash(const void *node, uint8_t *hash);
+void mst_node_calc_hash(const void *node, uint8_t *hash);
+void hash_digest_init(void);
+void hash_digest_update(const void *buf, int len);
+void hash_digest_final(void *hash, unsigned int *len);
+int init_authentication(void);
+int sign_superblock_node(void *node);
+int authenticated(void);
+
+extern EVP_MD_CTX *hash_md;
+extern const EVP_MD *md;
+
+#else
+static inline void ubifs_node_calc_hash(__attribute__((unused)) const void *node,
+					__attribute__((unused)) uint8_t *hash)
+{
+}
+
+static inline void mst_node_calc_hash(__attribute__((unused)) const void *node,
+				      __attribute__((unused)) uint8_t *hash)
+{
+}
+
+static inline void hash_digest_init(void)
+{
+}
+
+static inline void hash_digest_update(__attribute__((unused)) const void *buf,
+				      __attribute__((unused)) int len)
+{
+}
+
+static inline void hash_digest_final(__attribute__((unused)) void *hash,
+				     __attribute__((unused)) unsigned int *len)
+{
+}
+
+static inline int init_authentication(void)
+{
+	return 0;
+}
+
+static inline int sign_superblock_node(__attribute__((unused)) void *node)
+{
+	return 0;
+}
+
+static inline int authenticated(void)
+{
+	return 0;
+}
+
+#endif
+
+#endif /* __UBIFS_SIGN_H__ */
diff --git a/ubifs-utils/mkfs.ubifs/ubifs.h b/ubifs-utils/mkfs.ubifs/ubifs.h
index c26d094..55937ce 100644
--- a/ubifs-utils/mkfs.ubifs/ubifs.h
+++ b/ubifs-utils/mkfs.ubifs/ubifs.h
@@ -342,6 +342,15 @@ struct ubifs_znode
  * @lsave_offs: offset of LPT's save table
  * @lsave: LPT's save table
  * @lscan_lnum: LEB number of last LPT scan
+ *
+ * @hash_algo_name: the name of the hashing algorithm to use
+ * @hash_algo: The hash algo number (from include/linux/hash_info.h)
+ * @auth_key_filename: authentication key file name
+ * @x509_filename: x509 certificate file name for authentication
+ * @hash_len: the length of the hash
+ * @root_idx_hash: The hash of the root index node
+ * @lpt_hash: The hash of the LPT
+ * @mst_hash: The hash of the master node
  */
 struct ubifs_info
 {
@@ -423,6 +432,14 @@ struct ubifs_info
 	int *lsave;
 	int lscan_lnum;
 
+	char *hash_algo_name;
+	int hash_algo;
+	char *auth_key_filename;
+	char *auth_cert_filename;
+	int hash_len;
+	uint8_t root_idx_hash[UBIFS_MAX_HASH_LEN];
+	uint8_t lpt_hash[UBIFS_MAX_HASH_LEN];
+	uint8_t mst_hash[UBIFS_MAX_HASH_LEN];
 };
 
 /**
@@ -432,7 +449,8 @@ struct ubifs_info
  */
 static inline int ubifs_idx_node_sz(const struct ubifs_info *c, int child_cnt)
 {
-	return UBIFS_IDX_NODE_SZ + (UBIFS_BRANCH_SZ + c->key_len) * child_cnt;
+	return UBIFS_IDX_NODE_SZ + (UBIFS_BRANCH_SZ + c->key_len + c->hash_len)
+				    * child_cnt;
 }
 
 /**
@@ -447,7 +465,7 @@ struct ubifs_branch *ubifs_idx_branch(const struct ubifs_info *c,
 				      int bnum)
 {
 	return (struct ubifs_branch *)((void *)idx->branches +
-				       (UBIFS_BRANCH_SZ + c->key_len) * bnum);
+				       (UBIFS_BRANCH_SZ + c->key_len + c->hash_len) * bnum);
 }
 
 #endif /* __UBIFS_H__ */
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/2] mtd-utils: mkfs.ubifs: Add signing support for UBIFS images
  2019-08-06 10:49 [PATCH 0/2] mtd-utils: mkfs.ubifs: Add signing support for UBIFS images Sascha Hauer
  2019-08-06 10:49 ` [PATCH 1/2] ubifs-media: Update to Linux-5.3-rc3 Sascha Hauer
  2019-08-06 10:49 ` [PATCH 2/2] mkfs.ubifs: Add authentication support Sascha Hauer
@ 2019-08-19  7:29 ` David Oberhollenzer
  2020-02-07 15:25 ` Kevin Raymond
  3 siblings, 0 replies; 10+ messages in thread
From: David Oberhollenzer @ 2019-08-19  7:29 UTC (permalink / raw)
  To: Sascha Hauer, linux-mtd; +Cc: Richard Weinberger

Applied to mtd-utils.git master.

Thanks,

David

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/2] mtd-utils: mkfs.ubifs: Add signing support for UBIFS images
  2019-08-06 10:49 [PATCH 0/2] mtd-utils: mkfs.ubifs: Add signing support for UBIFS images Sascha Hauer
                   ` (2 preceding siblings ...)
  2019-08-19  7:29 ` [PATCH 0/2] mtd-utils: mkfs.ubifs: Add signing support for UBIFS images David Oberhollenzer
@ 2020-02-07 15:25 ` Kevin Raymond
  2020-02-07 15:51   ` Sascha Hauer
  3 siblings, 1 reply; 10+ messages in thread
From: Kevin Raymond @ 2020-02-07 15:25 UTC (permalink / raw)
  To: linux-mtd; +Cc: Richard Weinberger, Sascha Hauer, david.oberhollenzer

Hi there,

I am testing ubifs authentication for my new board, however I can't
git it to work.
I am not able to have keyctl add my key to the kernel keyring.

This is by far the most easier documentation I found about ubifs authentication.

I've got my kernel generating the asymmetric key, I can do the offline
signing with mkfs.ubifs but am not able to mount the ubifs partition.
I always get the following error:
    mount: mounting /dev/ubi0_8 on /mnt failed: Required key not available

I am really not sure about the "keyctl add" part.
From the Sascha example, should we change 'mysecret' by
'signing_key.pem' ? Should we change its format?
keyctl return me an identifier who does not appear to exist.
I don't have any new entry with the keyctl show command.

I am using Linux kernel 5.4.18, and mtd-utils from master (revision
95633c4dfe9).

I have the x509 certificate entry in /proc/keys (as asymmetri Build
time autogenerated kernel key)

My kernel config has the following entries:
CONFIG_UBIFS_FS_AUTHENTICATION=y
CONFIG_CRYPTO_AUTHENC=m
CONFIG_KEYS=y
CONFIG_SYSTEM_TRUSTED_KEYS=""
CONFIG_MODULE_SIG_FORMAT=y
CONFIG_MODULE_SIG=y
CONFIG_MODULE_SIG_SHA256=y
CONFIG_MODULE_SIG_HASH="sha256"
CONFIG_MODULE_SIG_KEY="certs/signing_key.pem"

Thanks for your help, I am not sure if ubifs authentication is widely used yet.




On Tue, Aug 6, 2019 at 12:49 PM Sascha Hauer <s.hauer@pengutronix.de> wrote:
>
> This series adds the userspace part to mkfs.ubifs to generate signed UBIFS
> images. With this a UBIFS image can be cryptographically signed in PKCS
> #7 CMS format which is then authenticated in the Kernel before mounting
> it. The necessary Kernel bits have been merged with 817aa094842d
> ("ubifs: support offline signed images").
>
> Here is a quick walkthrough for generating and mounting a signed UBIFS image
> using the kernel provided keys used for module signing:
>
> - configure kernel with CONFIG_UBIFS_FS_AUTHENTICATION, CONFIG_MODULE_SIG and
>   CONFIG_INTEGRITY_ASYMMETRIC_KEYS enabled (assumed to be in ~/linux/ in
>   this example)
> - build kernel, ~/linux/certs/signing_key.x509 and ~/linux/certs/signing_key.pem
>   will be generated
> - generate ubifs image:
>
>   mkfs.ubifs --hash-algo=sha256 --auth-cert=~/linux/certs/signing_key.x509 \
>         -d root -e  126976 -o ~/signed.ubifs -c 1024 -m 2048 \
>         --auth-key=~/linux/certs/signing_key.pem
>
> - flash UBIFS image onto target and mount:
>
>   ubimkvol -N root -s 64MiB /dev/ubi0
>   ubiupdatevol /dev/ubi0_0 signed.ubifs
>   cat mysecret | keyctl padd logon ubifs:root @s
>   mount -t ubifs /dev/ubi0_0 /mnt/ -o auth_hash_name=sha256,auth_key=ubifs:root
>
>
> Sascha Hauer (2):
>   ubifs-media: Update to Linux-5.3-rc3
>   mkfs.ubifs: Add authentication support
>
>  include/mtd/ubifs-media.h           |  75 ++++-
>  ubifs-utils/Makemodule.am           |   3 +-
>  ubifs-utils/mkfs.ubifs/lpt.c        |  12 +
>  ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 172 +++++++++---
>  ubifs-utils/mkfs.ubifs/mkfs.ubifs.h |   1 +
>  ubifs-utils/mkfs.ubifs/sign.c       | 409 ++++++++++++++++++++++++++++
>  ubifs-utils/mkfs.ubifs/sign.h       |  80 ++++++
>  ubifs-utils/mkfs.ubifs/ubifs.h      |  22 +-
>  8 files changed, 730 insertions(+), 44 deletions(-)
>  create mode 100644 ubifs-utils/mkfs.ubifs/sign.c
>  create mode 100644 ubifs-utils/mkfs.ubifs/sign.h
>
> --
> 2.20.1
>
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/2] mtd-utils: mkfs.ubifs: Add signing support for UBIFS images
  2020-02-07 15:25 ` Kevin Raymond
@ 2020-02-07 15:51   ` Sascha Hauer
  2020-02-07 17:20     ` Kevin Raymond
  0 siblings, 1 reply; 10+ messages in thread
From: Sascha Hauer @ 2020-02-07 15:51 UTC (permalink / raw)
  To: Kevin Raymond; +Cc: Richard Weinberger, linux-mtd, david.oberhollenzer

Hi Kevin,

On Fri, Feb 07, 2020 at 04:25:58PM +0100, Kevin Raymond wrote:
> Hi there,
> 
> I am testing ubifs authentication for my new board, however I can't
> git it to work.
> I am not able to have keyctl add my key to the kernel keyring.
> 
> This is by far the most easier documentation I found about ubifs authentication.
> 
> I've got my kernel generating the asymmetric key, I can do the offline
> signing with mkfs.ubifs but am not able to mount the ubifs partition.
> I always get the following error:
>     mount: mounting /dev/ubi0_8 on /mnt failed: Required key not available
> 
> I am really not sure about the "keyctl add" part.
> From the Sascha example, should we change 'mysecret' by
> 'signing_key.pem' ? Should we change its format?

There are two different keys involved. One is an asymmetric
private/public key pair needed for authenticating offline signed images.
That's the one you compile the Kernel with and which you provide to
mkfs.ubifs. This key is only used during first mount.

The other one is a symmetric key which is used during runtime and that's
the one you add with:

cat mysecret | keyctl padd logon ubifs:root @s

Note that "cat mysecret" is only an example. It obviously doesn't help
authenticating having a key stored world readable on the device. The
i.MX6 offers ways to generate secrets with the CAAM unit. However,
for testing purposes some "echo foobarbaz | keyctl padd logon ubifs:root
@s" does it.

You are trying offline signed images, but maybe you should start without
an image and do runtime authentication only. For this create an empty
UBI volume and just mount it like this (after doing the keyctl padd as
above):

mount -t ubifs /dev/ubi0_0 /mnt/ -o auth_hash_name=sha256,auth_key=ubifs:root

I am not sure if the kernel can read the key if you put it into the
session keyring. Systemd for example influences this and I don't know
exactly how. You might have to replace "@s" with "@u".

Hope that helps.

Regards
 Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/2] mtd-utils: mkfs.ubifs: Add signing support for UBIFS images
  2020-02-07 15:51   ` Sascha Hauer
@ 2020-02-07 17:20     ` Kevin Raymond
  2020-02-10  7:57       ` Sascha Hauer
  0 siblings, 1 reply; 10+ messages in thread
From: Kevin Raymond @ 2020-02-07 17:20 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: Richard Weinberger, linux-mtd, david.oberhollenzer

On Fri, Feb 7, 2020 at 4:51 PM Sascha Hauer <s.hauer@pengutronix.de> wrote:
>
> Hi Kevin,
>
> On Fri, Feb 07, 2020 at 04:25:58PM +0100, Kevin Raymond wrote:
> > Hi there,
> >
> > I am testing ubifs authentication for my new board, however I can't
> > git it to work.
> > I am not able to have keyctl add my key to the kernel keyring.
> >
> > This is by far the most easier documentation I found about ubifs authentication.
> >
> > I've got my kernel generating the asymmetric key, I can do the offline
> > signing with mkfs.ubifs but am not able to mount the ubifs partition.
> > I always get the following error:
> >     mount: mounting /dev/ubi0_8 on /mnt failed: Required key not available
> >
> > I am really not sure about the "keyctl add" part.
> > From the Sascha example, should we change 'mysecret' by
> > 'signing_key.pem' ? Should we change its format?
>
> There are two different keys involved. One is an asymmetric
> private/public key pair needed for authenticating offline signed images.
> That's the one you compile the Kernel with and which you provide to
> mkfs.ubifs. This key is only used during first mount.
>
> The other one is a symmetric key which is used during runtime and that's
> the one you add with:
>
> cat mysecret | keyctl padd logon ubifs:root @s
>
> Note that "cat mysecret" is only an example. It obviously doesn't help
> authenticating having a key stored world readable on the device. The
> i.MX6 offers ways to generate secrets with the CAAM unit. However,
> for testing purposes some "echo foobarbaz | keyctl padd logon ubifs:root
> @s" does it.

Alright I get it, the offline signing key is not the same as the one used at
runtime (which is definitly a good thing).

>
> You are trying offline signed images, but maybe you should start without
> an image and do runtime authentication only. For this create an empty
> UBI volume and just mount it like this (after doing the keyctl padd as
> above):
>
> mount -t ubifs /dev/ubi0_0 /mnt/ -o auth_hash_name=sha256,auth_key=ubifs:root
>
> I am not sure if the kernel can read the key if you put it into the
> session keyring. Systemd for example influences this and I don't know
> exactly how. You might have to replace "@s" with "@u".

Ok, using user session keyring is better in my example I can successfully define
a new symmetric key in order to mount a newly created partition.
I am not using systemd here, a simple busybox and sysV init.

However if I get the whole idea, If I use ubiupdatevol to update my partition,
I need the public key used while signing the ubifs at the first mount time
and then an other symmetric one ("mysecret" identified as 'ubifs:root' in this
exemple) in order to keep signing the partition.

This public key is already present (available to the mount command?) but
I don't have a way to tell which one to use.

mount -t ubifs /dev/ubi0_8 -o auth_key=ubifs:root,auth_hash_name=sha256 /mnt/
mount: mounting /dev/ubi0_8 on /mnt/ failed: Invalid argument

auth_key is the new symmetric key
my public key used when creating the offline signature is in /proc/keys

3b1ecf1d I------     1 perm 1f030000     0     0 asymmetri Build time
autogenerated kernel key: a21494c43b8859eceedf1c3d6727fd26f51b1bea:
X509.rsa f51b1bea []

I am not sure what I am missing about the first mount of a signed ubifs.

>
> Hope that helps.

Yes I get most of it now, thanks

>
> Regards
>  Sascha
>
> --
> Pengutronix e.K.                           |                             |
> Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
> 31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/2] mtd-utils: mkfs.ubifs: Add signing support for UBIFS images
  2020-02-07 17:20     ` Kevin Raymond
@ 2020-02-10  7:57       ` Sascha Hauer
  2020-02-10 17:06         ` Kevin Raymond
  0 siblings, 1 reply; 10+ messages in thread
From: Sascha Hauer @ 2020-02-10  7:57 UTC (permalink / raw)
  To: Kevin Raymond; +Cc: Richard Weinberger, linux-mtd, david.oberhollenzer

On Fri, Feb 07, 2020 at 06:20:57PM +0100, Kevin Raymond wrote:
> On Fri, Feb 7, 2020 at 4:51 PM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> >
> > Hi Kevin,
> >
> > On Fri, Feb 07, 2020 at 04:25:58PM +0100, Kevin Raymond wrote:
> > > Hi there,
> > >
> > > I am testing ubifs authentication for my new board, however I can't
> > > git it to work.
> > > I am not able to have keyctl add my key to the kernel keyring.
> > >
> > > This is by far the most easier documentation I found about ubifs authentication.
> > >
> > > I've got my kernel generating the asymmetric key, I can do the offline
> > > signing with mkfs.ubifs but am not able to mount the ubifs partition.
> > > I always get the following error:
> > >     mount: mounting /dev/ubi0_8 on /mnt failed: Required key not available
> > >
> > > I am really not sure about the "keyctl add" part.
> > > From the Sascha example, should we change 'mysecret' by
> > > 'signing_key.pem' ? Should we change its format?
> >
> > There are two different keys involved. One is an asymmetric
> > private/public key pair needed for authenticating offline signed images.
> > That's the one you compile the Kernel with and which you provide to
> > mkfs.ubifs. This key is only used during first mount.
> >
> > The other one is a symmetric key which is used during runtime and that's
> > the one you add with:
> >
> > cat mysecret | keyctl padd logon ubifs:root @s
> >
> > Note that "cat mysecret" is only an example. It obviously doesn't help
> > authenticating having a key stored world readable on the device. The
> > i.MX6 offers ways to generate secrets with the CAAM unit. However,
> > for testing purposes some "echo foobarbaz | keyctl padd logon ubifs:root
> > @s" does it.
> 
> Alright I get it, the offline signing key is not the same as the one used at
> runtime (which is definitly a good thing).
> 
> >
> > You are trying offline signed images, but maybe you should start without
> > an image and do runtime authentication only. For this create an empty
> > UBI volume and just mount it like this (after doing the keyctl padd as
> > above):
> >
> > mount -t ubifs /dev/ubi0_0 /mnt/ -o auth_hash_name=sha256,auth_key=ubifs:root
> >
> > I am not sure if the kernel can read the key if you put it into the
> > session keyring. Systemd for example influences this and I don't know
> > exactly how. You might have to replace "@s" with "@u".
> 
> Ok, using user session keyring is better in my example I can successfully define
> a new symmetric key in order to mount a newly created partition.
> I am not using systemd here, a simple busybox and sysV init.
> 
> However if I get the whole idea, If I use ubiupdatevol to update my partition,
> I need the public key used while signing the ubifs at the first mount time
> and then an other symmetric one ("mysecret" identified as 'ubifs:root' in this
> exemple) in order to keep signing the partition.

Yes. You could do without the symmetric key in a readonly environment.

> 
> This public key is already present (available to the mount command?) but
> I don't have a way to tell which one to use.

You don't have to, the Kernel will pick the right one automatically.

> 
> mount -t ubifs /dev/ubi0_8 -o auth_key=ubifs:root,auth_hash_name=sha256 /mnt/
> mount: mounting /dev/ubi0_8 on /mnt/ failed: Invalid argument
> 
> auth_key is the new symmetric key
> my public key used when creating the offline signature is in /proc/keys
> 
> 3b1ecf1d I------     1 perm 1f030000     0     0 asymmetri Build time
> autogenerated kernel key: a21494c43b8859eceedf1c3d6727fd26f51b1bea:
> X509.rsa f51b1bea []
> 
> I am not sure what I am missing about the first mount of a signed ubifs.

Me neither currently. I could play it through with a current
Linux/mtd-utils tomorrow to see if there's anything not working.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/2] mtd-utils: mkfs.ubifs: Add signing support for UBIFS images
  2020-02-10  7:57       ` Sascha Hauer
@ 2020-02-10 17:06         ` Kevin Raymond
  2020-02-11  8:12           ` Sascha Hauer
  0 siblings, 1 reply; 10+ messages in thread
From: Kevin Raymond @ 2020-02-10 17:06 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: Richard Weinberger, linux-mtd, david.oberhollenzer

On Mon, Feb 10, 2020 at 8:57 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
>
> On Fri, Feb 07, 2020 at 06:20:57PM +0100, Kevin Raymond wrote:
> > On Fri, Feb 7, 2020 at 4:51 PM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> > >
> > > Hi Kevin,
> > >
> > > On Fri, Feb 07, 2020 at 04:25:58PM +0100, Kevin Raymond wrote:
> > > > Hi there,
> > > >
> > > > I am testing ubifs authentication for my new board, however I can't
> > > > git it to work.
> > > > I am not able to have keyctl add my key to the kernel keyring.
> > > >
> > > > This is by far the most easier documentation I found about ubifs authentication.
> > > >
> > > > I've got my kernel generating the asymmetric key, I can do the offline
> > > > signing with mkfs.ubifs but am not able to mount the ubifs partition.
> > > > I always get the following error:
> > > >     mount: mounting /dev/ubi0_8 on /mnt failed: Required key not available
> > > >
> > > > I am really not sure about the "keyctl add" part.
> > > > From the Sascha example, should we change 'mysecret' by
> > > > 'signing_key.pem' ? Should we change its format?
> > >
> > > There are two different keys involved. One is an asymmetric
> > > private/public key pair needed for authenticating offline signed images.
> > > That's the one you compile the Kernel with and which you provide to
> > > mkfs.ubifs. This key is only used during first mount.
> > >
> > > The other one is a symmetric key which is used during runtime and that's
> > > the one you add with:
> > >
> > > cat mysecret | keyctl padd logon ubifs:root @s
> > >
> > > Note that "cat mysecret" is only an example. It obviously doesn't help
> > > authenticating having a key stored world readable on the device. The
> > > i.MX6 offers ways to generate secrets with the CAAM unit. However,
> > > for testing purposes some "echo foobarbaz | keyctl padd logon ubifs:root
> > > @s" does it.
> >
> > Alright I get it, the offline signing key is not the same as the one used at
> > runtime (which is definitly a good thing).
> >
> > >
> > > You are trying offline signed images, but maybe you should start without
> > > an image and do runtime authentication only. For this create an empty
> > > UBI volume and just mount it like this (after doing the keyctl padd as
> > > above):
> > >
> > > mount -t ubifs /dev/ubi0_0 /mnt/ -o auth_hash_name=sha256,auth_key=ubifs:root
> > >
> > > I am not sure if the kernel can read the key if you put it into the
> > > session keyring. Systemd for example influences this and I don't know
> > > exactly how. You might have to replace "@s" with "@u".
> >
> > Ok, using user session keyring is better in my example I can successfully define
> > a new symmetric key in order to mount a newly created partition.
> > I am not using systemd here, a simple busybox and sysV init.
> >
> > However if I get the whole idea, If I use ubiupdatevol to update my partition,
> > I need the public key used while signing the ubifs at the first mount time
> > and then an other symmetric one ("mysecret" identified as 'ubifs:root' in this
> > exemple) in order to keep signing the partition.
>
> Yes. You could do without the symmetric key in a readonly environment.
>
> >
> > This public key is already present (available to the mount command?) but
> > I don't have a way to tell which one to use.
>
> You don't have to, the Kernel will pick the right one automatically.
>
> >
> > mount -t ubifs /dev/ubi0_8 -o auth_key=ubifs:root,auth_hash_name=sha256 /mnt/
> > mount: mounting /dev/ubi0_8 on /mnt/ failed: Invalid argument
> >
> > auth_key is the new symmetric key
> > my public key used when creating the offline signature is in /proc/keys
> >
> > 3b1ecf1d I------     1 perm 1f030000     0     0 asymmetri Build time
> > autogenerated kernel key: a21494c43b8859eceedf1c3d6727fd26f51b1bea:
> > X509.rsa f51b1bea []
> >
> > I am not sure what I am missing about the first mount of a signed ubifs.
>
> Me neither currently. I could play it through with a current
> Linux/mtd-utils tomorrow to see if there's anything not working.


Ok, thanks a lot for your help.
I tried from scratch (auto generated kernel certificate/key, offline
signing using this key+certificate) and I still get the following:

    # mount -t ubifs /dev/ubi0_6 -o ro /mnt
    mount: mounting /dev/ubi0_6 on /mnt failed: Invalid argument
    [ 7961.936787] UBIFS error (ubi0:6 pid 1025):
ubifs_read_superblock: authenticated FS found, but no key given

Apparently I need the symmetric key, as the following is working now
(with or without the read-only option)

    mount -t ubifs /dev/ubi0_6 -o
ro,auth_key=ubifs:rootf,auth_hash_name=sha256  /mnt
    [ 8390.028045] UBIFS (ubi0:6): Mounting in authenticated mode
    [ 8618.586641] UBIFS (ubi0:6): background thread "ubifs_bgt0_6" stops
    [ 8630.039989] UBIFS (ubi0:6): Mounting in authenticated mode
    [ 8630.098767] UBIFS (ubi0:6): Successfully verified super block signature
    [ 8630.151322] UBIFS (ubi0:6): UBIFS: mounted UBI device 0, volume
6, name "root", R/O mode
    [ 8630.159482] UBIFS (ubi0:6): LEB size: 126976 bytes (124 KiB),
min./max. I/O unit sizes: 2048 bytes/2048 bytes
    [ 8630.169370] UBIFS (ubi0:6): FS size: 33267712 bytes (31 MiB,
262 LEBs), journal size 9023488 bytes (8 MiB, 72 LEBs)
    [ 8630.179784] UBIFS (ubi0:6): reserved for root: 0 bytes (0 KiB)
    [ 8630.185546] UBIFS (ubi0:6): media format: w4/r0 (latest is
w5/r0), UUID 33053EA9-B76E-47A1-BC0B-BB8B97E7F593, small LPT model

I don't know what was wrong last Friday, it might be the symmetric key
inserted with keyctl in an invalid format. This time a tried with a
simple ascii string.
I now have a working example, which is enough for me to dig further
into the ubifs authentication feature.

Thanks a lot for your work and your help.

>
> Sascha
>
> --
> Pengutronix e.K.                           |                             |
> Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
> 31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/2] mtd-utils: mkfs.ubifs: Add signing support for UBIFS images
  2020-02-10 17:06         ` Kevin Raymond
@ 2020-02-11  8:12           ` Sascha Hauer
  0 siblings, 0 replies; 10+ messages in thread
From: Sascha Hauer @ 2020-02-11  8:12 UTC (permalink / raw)
  To: Kevin Raymond; +Cc: Richard Weinberger, linux-mtd, david.oberhollenzer

On Mon, Feb 10, 2020 at 06:06:28PM +0100, Kevin Raymond wrote:
> On Mon, Feb 10, 2020 at 8:57 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> >
> > On Fri, Feb 07, 2020 at 06:20:57PM +0100, Kevin Raymond wrote:
> > > On Fri, Feb 7, 2020 at 4:51 PM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> > > >
> > > > Hi Kevin,
> > > >
> > > > On Fri, Feb 07, 2020 at 04:25:58PM +0100, Kevin Raymond wrote:
> > > > > Hi there,
> > > > >
> > > > > I am testing ubifs authentication for my new board, however I can't
> > > > > git it to work.
> > > > > I am not able to have keyctl add my key to the kernel keyring.
> > > > >
> > > > > This is by far the most easier documentation I found about ubifs authentication.
> > > > >
> > > > > I've got my kernel generating the asymmetric key, I can do the offline
> > > > > signing with mkfs.ubifs but am not able to mount the ubifs partition.
> > > > > I always get the following error:
> > > > >     mount: mounting /dev/ubi0_8 on /mnt failed: Required key not available
> > > > >
> > > > > I am really not sure about the "keyctl add" part.
> > > > > From the Sascha example, should we change 'mysecret' by
> > > > > 'signing_key.pem' ? Should we change its format?
> > > >
> > > > There are two different keys involved. One is an asymmetric
> > > > private/public key pair needed for authenticating offline signed images.
> > > > That's the one you compile the Kernel with and which you provide to
> > > > mkfs.ubifs. This key is only used during first mount.
> > > >
> > > > The other one is a symmetric key which is used during runtime and that's
> > > > the one you add with:
> > > >
> > > > cat mysecret | keyctl padd logon ubifs:root @s
> > > >
> > > > Note that "cat mysecret" is only an example. It obviously doesn't help
> > > > authenticating having a key stored world readable on the device. The
> > > > i.MX6 offers ways to generate secrets with the CAAM unit. However,
> > > > for testing purposes some "echo foobarbaz | keyctl padd logon ubifs:root
> > > > @s" does it.
> > >
> > > Alright I get it, the offline signing key is not the same as the one used at
> > > runtime (which is definitly a good thing).
> > >
> > > >
> > > > You are trying offline signed images, but maybe you should start without
> > > > an image and do runtime authentication only. For this create an empty
> > > > UBI volume and just mount it like this (after doing the keyctl padd as
> > > > above):
> > > >
> > > > mount -t ubifs /dev/ubi0_0 /mnt/ -o auth_hash_name=sha256,auth_key=ubifs:root
> > > >
> > > > I am not sure if the kernel can read the key if you put it into the
> > > > session keyring. Systemd for example influences this and I don't know
> > > > exactly how. You might have to replace "@s" with "@u".
> > >
> > > Ok, using user session keyring is better in my example I can successfully define
> > > a new symmetric key in order to mount a newly created partition.
> > > I am not using systemd here, a simple busybox and sysV init.
> > >
> > > However if I get the whole idea, If I use ubiupdatevol to update my partition,
> > > I need the public key used while signing the ubifs at the first mount time
> > > and then an other symmetric one ("mysecret" identified as 'ubifs:root' in this
> > > exemple) in order to keep signing the partition.
> >
> > Yes. You could do without the symmetric key in a readonly environment.
> >
> > >
> > > This public key is already present (available to the mount command?) but
> > > I don't have a way to tell which one to use.
> >
> > You don't have to, the Kernel will pick the right one automatically.
> >
> > >
> > > mount -t ubifs /dev/ubi0_8 -o auth_key=ubifs:root,auth_hash_name=sha256 /mnt/
> > > mount: mounting /dev/ubi0_8 on /mnt/ failed: Invalid argument
> > >
> > > auth_key is the new symmetric key
> > > my public key used when creating the offline signature is in /proc/keys
> > >
> > > 3b1ecf1d I------     1 perm 1f030000     0     0 asymmetri Build time
> > > autogenerated kernel key: a21494c43b8859eceedf1c3d6727fd26f51b1bea:
> > > X509.rsa f51b1bea []
> > >
> > > I am not sure what I am missing about the first mount of a signed ubifs.
> >
> > Me neither currently. I could play it through with a current
> > Linux/mtd-utils tomorrow to see if there's anything not working.
> 
> 
> Ok, thanks a lot for your help.
> I tried from scratch (auto generated kernel certificate/key, offline
> signing using this key+certificate) and I still get the following:
> 
>     # mount -t ubifs /dev/ubi0_6 -o ro /mnt
>     mount: mounting /dev/ubi0_6 on /mnt failed: Invalid argument
>     [ 7961.936787] UBIFS error (ubi0:6 pid 1025):
> ubifs_read_superblock: authenticated FS found, but no key given

Ok, this is something worth changing. The key is only needed once we go
rw.

> 
> Apparently I need the symmetric key, as the following is working now
> (with or without the read-only option)
> 
>     mount -t ubifs /dev/ubi0_6 -o
> ro,auth_key=ubifs:rootf,auth_hash_name=sha256  /mnt
>     [ 8390.028045] UBIFS (ubi0:6): Mounting in authenticated mode
>     [ 8618.586641] UBIFS (ubi0:6): background thread "ubifs_bgt0_6" stops
>     [ 8630.039989] UBIFS (ubi0:6): Mounting in authenticated mode
>     [ 8630.098767] UBIFS (ubi0:6): Successfully verified super block signature
>     [ 8630.151322] UBIFS (ubi0:6): UBIFS: mounted UBI device 0, volume
> 6, name "root", R/O mode
>     [ 8630.159482] UBIFS (ubi0:6): LEB size: 126976 bytes (124 KiB),
> min./max. I/O unit sizes: 2048 bytes/2048 bytes
>     [ 8630.169370] UBIFS (ubi0:6): FS size: 33267712 bytes (31 MiB,
> 262 LEBs), journal size 9023488 bytes (8 MiB, 72 LEBs)
>     [ 8630.179784] UBIFS (ubi0:6): reserved for root: 0 bytes (0 KiB)
>     [ 8630.185546] UBIFS (ubi0:6): media format: w4/r0 (latest is
> w5/r0), UUID 33053EA9-B76E-47A1-BC0B-BB8B97E7F593, small LPT model
> 
> I don't know what was wrong last Friday, it might be the symmetric key
> inserted with keyctl in an invalid format. This time a tried with a
> simple ascii string.
> I now have a working example, which is enough for me to dig further
> into the ubifs authentication feature.
> 
> Thanks a lot for your work and your help.

You're welcome. If anything is still not working don't hesitate to ask.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2020-02-11  8:12 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-06 10:49 [PATCH 0/2] mtd-utils: mkfs.ubifs: Add signing support for UBIFS images Sascha Hauer
2019-08-06 10:49 ` [PATCH 1/2] ubifs-media: Update to Linux-5.3-rc3 Sascha Hauer
2019-08-06 10:49 ` [PATCH 2/2] mkfs.ubifs: Add authentication support Sascha Hauer
2019-08-19  7:29 ` [PATCH 0/2] mtd-utils: mkfs.ubifs: Add signing support for UBIFS images David Oberhollenzer
2020-02-07 15:25 ` Kevin Raymond
2020-02-07 15:51   ` Sascha Hauer
2020-02-07 17:20     ` Kevin Raymond
2020-02-10  7:57       ` Sascha Hauer
2020-02-10 17:06         ` Kevin Raymond
2020-02-11  8:12           ` Sascha Hauer

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).