aboutsummaryrefslogtreecommitdiff
path: root/ubifs-utils/libubifs/auth.c
diff options
context:
space:
mode:
Diffstat (limited to 'ubifs-utils/libubifs/auth.c')
-rw-r--r--ubifs-utils/libubifs/auth.c175
1 files changed, 175 insertions, 0 deletions
diff --git a/ubifs-utils/libubifs/auth.c b/ubifs-utils/libubifs/auth.c
new file mode 100644
index 0000000..fab1dba
--- /dev/null
+++ b/ubifs-utils/libubifs/auth.c
@@ -0,0 +1,175 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * This file is part of UBIFS.
+ *
+ * Copyright (C) 2018 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
+ */
+
+/*
+ * This file implements various helper functions for UBIFS authentication support
+ */
+
+#include "linux_err.h"
+#include "ubifs.h"
+#include "sign.h"
+#include "defs.h"
+
+int ubifs_shash_init(const struct ubifs_info *c,
+ __unused struct shash_desc *desc)
+{
+ if (ubifs_authenticated(c))
+ return hash_digest_init();
+ else
+ return 0;
+}
+
+int ubifs_shash_update(const struct ubifs_info *c,
+ __unused struct shash_desc *desc,
+ const void *buf, unsigned int len)
+{
+ int err = 0;
+
+ if (ubifs_authenticated(c)) {
+ err = hash_digest_update(buf, len);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+int ubifs_shash_final(const struct ubifs_info *c,
+ __unused struct shash_desc *desc, u8 *out)
+{
+ return ubifs_authenticated(c) ? hash_digest_final(out) : 0;
+}
+
+struct shash_desc *ubifs_hash_get_desc(const struct ubifs_info *c)
+{
+ int err;
+
+ err = ubifs_shash_init(c, NULL);
+ if (err)
+ return ERR_PTR(err);
+
+ return NULL;
+}
+
+/**
+ * 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
+ *
+ * Returns 0 for success or a negative error code otherwise.
+ */
+int __ubifs_node_calc_hash(__unused const struct ubifs_info *c,
+ const void *node, u8 *hash)
+{
+ const struct ubifs_ch *ch = node;
+
+ return hash_digest(node, le32_to_cpu(ch->len), hash);
+}
+
+/**
+ * ubifs_master_node_calc_hash - calculate the hash of a UBIFS master node
+ * @node: the node to calculate a hash for
+ * @hash: the returned hash
+ */
+int ubifs_master_node_calc_hash(const struct ubifs_info *c, const void *node,
+ uint8_t *hash)
+{
+ if (!ubifs_authenticated(c))
+ return 0;
+
+ return hash_digest(node + sizeof(struct ubifs_ch),
+ UBIFS_MST_NODE_SZ - sizeof(struct ubifs_ch), hash);
+}
+
+int ubifs_sign_superblock_node(struct ubifs_info *c, void *node)
+{
+ int err, len;
+ struct ubifs_sig_node *sig = node + UBIFS_SB_NODE_SZ;
+
+ if (!ubifs_authenticated(c))
+ return 0;
+
+ err = hash_sign_node(c->auth_key_filename, c->auth_cert_filename, node,
+ &len, sig + 1);
+ if (err)
+ return err;
+
+ sig->type = UBIFS_SIGNATURE_TYPE_PKCS7;
+ sig->len = cpu_to_le32(len);
+ sig->ch.node_type = UBIFS_SIG_NODE;
+
+ return 0;
+}
+
+/**
+ * ubifs_bad_hash - Report hash mismatches
+ * @c: UBIFS file-system description object
+ * @node: the node
+ * @hash: the expected hash
+ * @lnum: the LEB @node was read from
+ * @offs: offset in LEB @node was read from
+ *
+ * This function reports a hash mismatch when a node has a different hash than
+ * expected.
+ */
+void ubifs_bad_hash(const struct ubifs_info *c, const void *node, const u8 *hash,
+ int lnum, int offs)
+{
+ int len = min(c->hash_len, 20);
+ int cropped = len != c->hash_len;
+ const char *cont = cropped ? "..." : "";
+
+ u8 calc[UBIFS_HASH_ARR_SZ];
+
+ __ubifs_node_calc_hash(c, node, calc);
+
+ ubifs_err(c, "hash mismatch on node at LEB %d:%d", lnum, offs);
+ ubifs_err(c, "hash expected: %*ph%s", len, hash, cont);
+ ubifs_err(c, "hash calculated: %*ph%s", len, calc, cont);
+}
+
+/**
+ * ubifs_init_authentication - initialize UBIFS authentication support
+ * @c: UBIFS file-system description object
+ *
+ * This function returns 0 for success or a negative error code otherwise.
+ */
+int ubifs_init_authentication(struct ubifs_info *c)
+{
+ int err, hash_len, hash_algo;
+
+ if (!c->auth_key_filename && !c->auth_cert_filename && !c->hash_algo_name)
+ return 0;
+
+ if (!c->auth_key_filename) {
+ ubifs_err(c, "authentication key not given (--auth-key)");
+ return -EINVAL;
+ }
+
+ if (!c->hash_algo_name) {
+ ubifs_err(c, "Hash algorithm not given (--hash-algo)");
+ return -EINVAL;
+ }
+
+ err = init_authentication(c->hash_algo_name, &hash_len, &hash_algo);
+ if (err) {
+ ubifs_err(c, "Init authentication failed");
+ return err;
+ }
+
+ c->hash_len = hash_len;
+ c->hash_algo = hash_algo;
+ c->authenticated = 1;
+
+ return 0;
+}
+
+void __ubifs_exit_authentication(__unused struct ubifs_info *c)
+{
+ exit_authentication();
+}