summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2015-12-08 08:29:02 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2015-12-08 08:29:02 +0100
commit2ae9bbba0742d79376eb26252b212913d9181bd8 (patch)
treed4905ffccf62b563d9d67bbae66648421cd3745c
parentfab8198323d88ec061032b406b0dc4a874096d60 (diff)
parent34cda8c23115b3ae3aeeeba7618d5d5654536494 (diff)
downloadbarebox-2ae9bbba0742d79376eb26252b212913d9181bd8.tar.gz
barebox-2ae9bbba0742d79376eb26252b212913d9181bd8.tar.xz
Merge branch 'for-next/state'
-rw-r--r--Documentation/devicetree/bindings/barebox/barebox,state.rst19
-rw-r--r--commands/state.c19
-rw-r--r--common/Kconfig18
-rw-r--r--common/state.c181
-rw-r--r--crypto/Kconfig10
-rw-r--r--crypto/Makefile1
-rw-r--r--crypto/keystore.c80
-rw-r--r--drivers/misc/state.c34
-rw-r--r--drivers/of/of_path.c96
-rw-r--r--include/crypto/keystore.h26
-rw-r--r--include/of.h1
-rw-r--r--include/state.h1
12 files changed, 373 insertions, 113 deletions
diff --git a/Documentation/devicetree/bindings/barebox/barebox,state.rst b/Documentation/devicetree/bindings/barebox/barebox,state.rst
index 4c5b06db47..ef66029372 100644
--- a/Documentation/devicetree/bindings/barebox/barebox,state.rst
+++ b/Documentation/devicetree/bindings/barebox/barebox,state.rst
@@ -32,6 +32,12 @@ Required properties:
* ``backend``: describes where the data for this state is stored
* ``backend-type``: should be ``raw`` or ``dtb``.
+Optional properties:
+
+* ``algo``: A HMAC algorithm used to detect manipulation of the data
+ or header, sensible values follow this pattern ``hmac(<HASH>)``,
+ e.g. ``hmac(sha256)``.
+
Variable nodes
--------------
@@ -105,6 +111,19 @@ devicetree description of the state itself, but additionally contains
the actual values of the variables. Unlike the raw state backend the
dtb state backend can describe itself.
+HMAC
+----
+
+With the optional property ``algo = "hmac(<HASH>)";`` a HMAC algorithm
+can be defined to detect unauthorized modification of the state's
+header and/or data. For this to work the HMAC and the selected hash
+algorithm have to be compiled into barebox.
+
+The shared secret for the HMAC is requested via
+``keystore_get_secret()``, using the state's name, from the barebox
+simple keystore. It's up to the developer to populate the keystore via
+``keystore_set_secret()`` in beforehand.
+
Frontend
--------
diff --git a/commands/state.c b/commands/state.c
index 59d1eb8502..4b51759e3e 100644
--- a/commands/state.c
+++ b/commands/state.c
@@ -21,26 +21,20 @@ static int do_state(int argc, char *argv[])
{
int opt, ret = 0;
struct state *state = NULL;
- int do_save = 0, do_load = 0;
+ int do_save = 0;
const char *statename = "state";
- while ((opt = getopt(argc, argv, "sl")) > 0) {
+ while ((opt = getopt(argc, argv, "s")) > 0) {
switch (opt) {
case 's':
do_save = 1;
break;
- case 'l':
- do_load = 1;
- break;
default:
return COMMAND_ERROR_USAGE;
}
}
- if (do_save && do_load)
- return COMMAND_ERROR_USAGE;
-
- if (!do_save && !do_load) {
+ if (!do_save) {
state_info();
return 0;
}
@@ -56,8 +50,6 @@ static int do_state(int argc, char *argv[])
if (do_save)
ret = state_save(state);
- else if (do_load)
- ret = state_load(state);
return ret;
}
@@ -67,13 +59,12 @@ BAREBOX_CMD_HELP_TEXT("Usage: state [OPTIONS] [STATENAME]")
BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("options:")
BAREBOX_CMD_HELP_OPT ("-s", "save state")
-BAREBOX_CMD_HELP_OPT ("-l", "load state")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(state)
.cmd = do_state,
- BAREBOX_CMD_DESC("load and save state information")
- BAREBOX_CMD_OPTS("[-sl] [STATENAME]")
+ BAREBOX_CMD_DESC("save state information")
+ BAREBOX_CMD_OPTS("[-s] [STATENAME]")
BAREBOX_CMD_GROUP(CMD_GRP_MISC)
BAREBOX_CMD_HELP(cmd_state_help)
BAREBOX_CMD_END
diff --git a/common/Kconfig b/common/Kconfig
index 877d3855a2..8e7950968c 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -751,6 +751,24 @@ config STATE
select OFTREE
select PARAMETER
+config STATE_CRYPTO
+ bool "HMAC based authentication support"
+ depends on STATE
+ select CRYPTO_KEYSTORE
+ select DIGEST
+ select DIGEST_HMAC_GENERIC
+ help
+ This options enables HMAC based authentication support for
+ the state's header and data. This means the state framework
+ can verify both the data integrity and the authentication of
+ the state's header and data.
+
+ Don't forget to select a hash algorithm in the
+ crypto/digests menu.
+
+ See Documentation/devicetree/bindings/barebox/barebox,state.rst
+ for more information.
+
config RESET_SOURCE
bool "detect Reset cause"
depends on GLOBALVAR
diff --git a/common/state.c b/common/state.c
index a161b94f3a..ec72dbd9a0 100644
--- a/common/state.c
+++ b/common/state.c
@@ -15,6 +15,7 @@
*/
#include <common.h>
+#include <digest.h>
#include <environment.h>
#include <errno.h>
#include <fcntl.h>
@@ -28,6 +29,8 @@
#include <state.h>
#include <xfuncs.h>
+#include <crypto/keystore.h>
+
#include <linux/mtd/mtd-abi.h>
#include <linux/mtd/mtd.h>
#include <linux/list.h>
@@ -41,7 +44,7 @@ struct state_backend;
struct state {
struct device_d dev;
- const struct device_node *root;
+ struct device_node *root;
struct list_head variables;
const char *name;
struct list_head list;
@@ -51,11 +54,11 @@ struct state {
};
struct state_backend {
- int (*load)(struct state_backend *backend, struct state *state);
int (*save)(struct state_backend *backend, struct state *state);
const char *name;
const char *of_path;
const char *path;
+ struct digest *digest;
};
enum state_variable_type {
@@ -951,6 +954,16 @@ static int of_state_fixup(struct device_node *root, void *ctx)
if (ret)
goto out;
+ if (state->backend->digest) {
+ p = of_new_property(new_node, "algo",
+ digest_name(state->backend->digest),
+ strlen(digest_name(state->backend->digest)) + 1);
+ if (!p) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ }
+
/* address-cells + size-cells */
ret = of_property_write_u32(new_node, "#address-cells", 1);
if (ret)
@@ -1051,30 +1064,6 @@ int state_get_name(const struct state *state, char const **name)
}
/*
- * state_load - load a state from the backing store
- *
- * @state The state instance to load
- */
-int state_load(struct state *state)
-{
- int ret;
-
- if (!state->backend)
- return -ENOSYS;
-
- ret = state->backend->load(state->backend, state);
- if (ret) {
- dev_warn(&state->dev, "load failed\n");
- state->dirty = 1;
- } else {
- dev_info(&state->dev, "load successful\n");
- state->dirty = 0;
- }
-
- return ret;
-}
-
-/*
* state_save - save a state to the backing store
*
* @state The state instance to save
@@ -1228,7 +1217,6 @@ int state_backend_dtb_file(struct state *state, const char *of_path, const char
backend_dtb = xzalloc(sizeof(*backend_dtb));
backend = &backend_dtb->backend;
- backend->load = state_backend_dtb_load;
backend->save = state_backend_dtb_save;
backend->of_path = xstrdup(of_path);
backend->path = xstrdup(path);
@@ -1240,6 +1228,15 @@ int state_backend_dtb_file(struct state *state, const char *of_path, const char
if (!ret && !(meminfo.flags & MTD_NO_ERASE))
backend_dtb->need_erase = true;
+ ret = state_backend_dtb_load(backend, state);
+ if (ret) {
+ dev_warn(&state->dev, "load failed - using defaults\n");
+ } else {
+ dev_info(&state->dev, "load successful\n");
+ state->dirty = 0;
+ }
+
+ /* ignore return value of load() */
return 0;
}
@@ -1249,7 +1246,7 @@ int state_backend_dtb_file(struct state *state, const char *of_path, const char
struct state_backend_raw {
struct state_backend backend;
unsigned long size_data; /* The raw data size (without header) */
- unsigned long size_full; /* The size header + raw data */
+ unsigned long size_full; /* The size header + raw data + hmac */
unsigned long stride; /* The stride size in bytes of the copies */
off_t offset; /* offset in the storage file */
size_t size; /* size of the storage area */
@@ -1272,8 +1269,9 @@ static int backend_raw_load_one(struct state_backend_raw *backend_raw,
struct state_variable *sv;
struct backend_raw_header header = {};
unsigned long max_len;
+ int d_len = 0;
int ret;
- void *buf;
+ void *buf, *data, *hmac;
max_len = backend_raw->stride;
@@ -1304,6 +1302,11 @@ static int backend_raw_load_one(struct state_backend_raw *backend_raw,
return -EINVAL;
}
+ if (backend_raw->backend.digest) {
+ d_len = digest_length(backend_raw->backend.digest);
+ max_len -= d_len;
+ }
+
if (header.data_len > max_len) {
dev_err(&state->dev,
"invalid data_len %u in header, max is %lu\n",
@@ -1311,13 +1314,19 @@ static int backend_raw_load_one(struct state_backend_raw *backend_raw,
return -EINVAL;
}
- buf = xzalloc(header.data_len);
+ buf = xzalloc(sizeof(header) + header.data_len + d_len);
+ data = buf + sizeof(header);
+ hmac = data + header.data_len;
+
+ ret = lseek(fd, offset, SEEK_SET);
+ if (ret < 0)
+ goto out_free;
- ret = read_full(fd, buf, header.data_len);
+ ret = read_full(fd, buf, sizeof(header) + header.data_len + d_len);
if (ret < 0)
goto out_free;
- crc = crc32(0, buf, header.data_len);
+ crc = crc32(0, data, header.data_len);
if (crc != header.data_crc) {
dev_err(&state->dev,
"invalid crc, calculated 0x%08x, found 0x%08x\n",
@@ -1326,10 +1335,27 @@ static int backend_raw_load_one(struct state_backend_raw *backend_raw,
goto out_free;
}
+ if (backend_raw->backend.digest) {
+ struct digest *d = backend_raw->backend.digest;
+
+ ret = digest_init(d);
+ if (ret)
+ goto out_free;
+
+ /* hmac over header and data */
+ ret = digest_update(d, buf, sizeof(header) + header.data_len);
+ if (ret)
+ goto out_free;
+
+ ret = digest_verify(d, hmac);
+ if (ret < 0)
+ goto out_free;
+ }
+
list_for_each_entry(sv, &state->variables, list) {
if (sv->start + sv->size > header.data_len)
break;
- memcpy(sv->raw, buf + sv->start, sv->size);
+ memcpy(sv->raw, data + sv->start, sv->size);
}
free(buf);
@@ -1406,7 +1432,7 @@ static int state_backend_raw_save(struct state_backend *backend,
struct state_backend_raw *backend_raw = container_of(backend,
struct state_backend_raw, backend);
int ret = 0, fd, i;
- void *buf, *data;
+ void *buf, *data, *hmac;
struct backend_raw_header *header;
struct state_variable *sv;
@@ -1414,6 +1440,7 @@ static int state_backend_raw_save(struct state_backend *backend,
header = buf;
data = buf + sizeof(*header);
+ hmac = data + backend_raw->size_data;
list_for_each_entry(sv, &state->variables, list)
memcpy(data + sv->start, sv->raw, sv->size);
@@ -1424,6 +1451,23 @@ static int state_backend_raw_save(struct state_backend *backend,
header->header_crc = crc32(0, header,
sizeof(*header) - sizeof(uint32_t));
+ if (backend_raw->backend.digest) {
+ struct digest *d = backend_raw->backend.digest;
+
+ ret = digest_init(d);
+ if (ret)
+ goto out_free;
+
+ /* hmac over header and data */
+ ret = digest_update(d, buf, sizeof(*header) + backend_raw->size_data);
+ if (ret)
+ goto out_free;
+
+ ret = digest_final(d, hmac);
+ if (ret < 0)
+ goto out_free;
+ }
+
fd = open(backend->path, O_WRONLY);
if (fd < 0)
goto out_free;
@@ -1508,6 +1552,53 @@ static int state_backend_raw_file_get_size(const char *path, size_t *out_size)
return ret;
}
+static int state_backend_raw_file_init_digest(struct state *state, struct state_backend_raw *backend_raw)
+{
+ struct digest *digest;
+ struct property *p;
+ const char *algo;
+ const unsigned char *key;
+ int key_len, ret;
+
+ p = of_find_property(state->root, "algo", NULL);
+ if (!p) /* does not exist */
+ return 0;
+
+ if (!IS_ENABLED(CONFIG_STATE_CRYPTO)) {
+ dev_err(&state->dev,
+ "algo %s specified, but crypto support for state framework (CONFIG_STATE_CRYPTO) not enabled.\n",
+ algo);
+ return -EINVAL;
+ }
+
+ ret = of_property_read_string(state->root, "algo", &algo);
+ if (ret)
+ return ret;
+
+ ret = keystore_get_secret(state->name, &key, &key_len);
+ if (ret == -ENOENT) /* -ENOENT == does not exist */
+ return -EPROBE_DEFER;
+ else if (ret)
+ return ret;
+
+ digest = digest_alloc(algo);
+ if (!digest) {
+ dev_info(&state->dev, "algo %s not found - probe deferred\n", algo);
+ return -EPROBE_DEFER;
+ }
+
+ ret = digest_set_key(digest, key, key_len);
+ if (ret) {
+ digest_free(digest);
+ return ret;
+ }
+
+ backend_raw->backend.digest = digest;
+ backend_raw->size_full = digest_length(digest);
+
+ return 0;
+}
+
/*
* state_backend_raw_file - create a raw file backend store for a state instance
*
@@ -1548,9 +1639,14 @@ int state_backend_raw_file(struct state *state, const char *of_path,
return -EINVAL;
backend_raw = xzalloc(sizeof(*backend_raw));
- backend = &backend_raw->backend;
- backend->load = state_backend_raw_load;
+ ret = state_backend_raw_file_init_digest(state, backend_raw);
+ if (ret) {
+ free(backend_raw);
+ return ret;
+ }
+
+ backend = &backend_raw->backend;
backend->save = state_backend_raw_save;
backend->of_path = xstrdup(of_path);
backend->path = xstrdup(path);
@@ -1560,7 +1656,7 @@ int state_backend_raw_file(struct state *state, const char *of_path,
backend_raw->size_data = sv->start + sv->size;
backend_raw->offset = offset;
backend_raw->size = size;
- backend_raw->size_full = backend_raw->size_data +
+ backend_raw->size_full += backend_raw->size_data +
sizeof(struct backend_raw_header);
state->backend = backend;
@@ -1585,8 +1681,19 @@ int state_backend_raw_file(struct state *state, const char *of_path,
goto err;
}
+ ret = state_backend_raw_load(backend, state);
+ if (ret) {
+ dev_warn(&state->dev, "load failed - using defaults\n");
+ } else {
+ dev_info(&state->dev, "load successful\n");
+ state->dirty = 0;
+ }
+
+ /* ignore return value of load() */
return 0;
err:
+ digest_free(backend_raw->backend.digest);
+
free(backend_raw);
return ret;
}
diff --git a/crypto/Kconfig b/crypto/Kconfig
index ef807dec68..41145a312d 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1,3 +1,5 @@
+menu "Crypto support"
+
config CRC32
bool
@@ -84,3 +86,11 @@ config CRYPTO_PBKDF2
select DIGEST
select DIGEST_SHA1_GENERIC
bool
+
+config CRYPTO_KEYSTORE
+ bool "Keystore"
+ help
+ This is a simple keystore, which can be used to pass keys
+ between several components via simple interface.
+
+endmenu
diff --git a/crypto/Makefile b/crypto/Makefile
index f39de718e5..c6d17787ca 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_DIGEST_SHA384_GENERIC) += sha4.o
obj-$(CONFIG_DIGEST_SHA512_GENERIC) += sha4.o
obj-$(CONFIG_CRYPTO_PBKDF2) += pbkdf2.o
+obj-$(CONFIG_CRYPTO_KEYSTORE) += keystore.o
diff --git a/crypto/keystore.c b/crypto/keystore.c
new file mode 100644
index 0000000000..90b470fe67
--- /dev/null
+++ b/crypto/keystore.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2015 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
+ *
+ * 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.
+ */
+
+#include <common.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+
+static LIST_HEAD(keystore_list);
+
+#define for_each_key(key) list_for_each_entry(key, &keystore_list, list)
+
+struct keystore_key {
+ struct list_head list;
+ const char *name;
+ const u8 *secret;
+ int secret_len;
+};
+
+static int keystore_compare(struct list_head *a, struct list_head *b)
+{
+ const char *na = list_entry(a, struct keystore_key, list)->name;
+ const char *nb = list_entry(b, struct keystore_key, list)->name;
+
+ return strcmp(na, nb);
+}
+
+/**
+ * @param[in] name Name of the secret to get
+ * @param[out] secret Double pointer to memory representing the secret, do _not_ free() after use
+ * @param[out] secret_len Pointer to length of the secret
+ */
+int keystore_get_secret(const char *name, const u8 **secret, int *secret_len)
+{
+ struct keystore_key *key;
+
+ for_each_key(key) {
+ if (!strcmp(name, key->name)) {
+ if (!secret || !secret_len)
+ return 0;
+
+ *secret = key->secret;
+ *secret_len = key->secret_len;
+
+ return 0;
+ }
+ }
+
+ return -ENOENT;
+}
+
+/**
+ * @param[in] name Name of the secret to set
+ * @param[in] secret Pointer to memory holding the secret
+ * @param[in] secret_len Length of the secret
+ */
+int keystore_set_secret(const char *name, const u8 *secret, int secret_len)
+{
+ struct keystore_key *key;
+ int ret;
+
+ /* check if key is already in store */
+ ret = keystore_get_secret(name, NULL, NULL);
+ if (!ret)
+ return -EBUSY;
+
+ key = xzalloc(sizeof(*key));
+ INIT_LIST_HEAD(&key->list);
+ key->name = xstrdup(name);
+ key->secret = xmemdup(secret, secret_len);
+ key->secret_len = secret_len;
+
+ list_add_sort(&key->list, &keystore_list, keystore_compare);
+
+ return 0;
+}
diff --git a/drivers/misc/state.c b/drivers/misc/state.c
index f3e366480f..73356b45a0 100644
--- a/drivers/misc/state.c
+++ b/drivers/misc/state.c
@@ -37,7 +37,7 @@ static int state_probe(struct device_d *dev)
alias = of_alias_get(np);
if (!alias)
- alias = "state";
+ alias = np->name;
state = state_new_from_node(alias, np);
if (IS_ERR(state))
@@ -52,34 +52,21 @@ static int state_probe(struct device_d *dev)
/* guess if of_path is a path, not a phandle */
if (of_path[0] == '/' && len > 1) {
ret = of_find_path(np, "backend", &path, 0);
- if (ret)
- goto out_release;
} else {
- struct device_d *dev;
- struct cdev *cdev;
partition_node = of_parse_phandle(np, "backend", 0);
- if (!partition_node) {
- ret = -ENODEV;
- goto out_release;
- }
-
- dev = of_find_device_by_node(partition_node);
- if (!list_is_singular(&dev->cdevs)) {
- ret = -ENODEV;
- goto out_release;
- }
-
- cdev = list_first_entry(&dev->cdevs, struct cdev, devices_list);
- if (!cdev) {
- ret = -ENODEV;
- goto out_release;
- }
-
- path = asprintf("/dev/%s", cdev->name);
+ if (!partition_node)
+ return -EINVAL;
+
of_path = partition_node->full_name;
+ ret = of_find_path_by_node(partition_node, &path, 0);
}
+ if (ret == -ENODEV)
+ ret = -EPROBE_DEFER;
+ if (ret)
+ goto out_release;
+
ret = of_property_read_string(np, "backend-type", &backend_type);
if (ret) {
goto out_free;
@@ -99,7 +86,6 @@ static int state_probe(struct device_d *dev)
dev_info(dev, "backend: %s, path: %s, of_path: %s\n", backend_type, path, of_path);
free(path);
- state_load(state);
return 0;
out_free:
diff --git a/drivers/of/of_path.c b/drivers/of/of_path.c
index 992972c9b5..6903905259 100644
--- a/drivers/of/of_path.c
+++ b/drivers/of/of_path.c
@@ -106,6 +106,63 @@ out:
return ret;
}
+static int __of_find_path(struct device_node *node, const char *propname, char **outpath, unsigned flags)
+{
+ struct of_path op = {};
+ const char *str;
+ bool add_bb = false;
+ int i, ret;
+
+ op.dev = of_find_device_by_node_path(node->full_name);
+ if (!op.dev) {
+ op.dev = of_find_device_by_node_path(node->parent->full_name);
+ if (!op.dev)
+ return -ENODEV;
+ }
+
+ device_detect(op.dev);
+
+ op.cdev = cdev_by_device_node(node);
+
+ i = 1;
+
+ while (propname) {
+ ret = of_property_read_string_index(node, propname, i++, &str);
+ if (ret)
+ break;
+
+ ret = of_path_parse_one(&op, str);
+ if (ret)
+ return ret;
+ }
+
+ if (!op.cdev)
+ return -ENOENT;
+
+ if ((flags & OF_FIND_PATH_FLAGS_BB) && op.cdev->mtd &&
+ mtd_can_have_bb(op.cdev->mtd))
+ add_bb = true;
+
+ *outpath = asprintf("/dev/%s%s", op.cdev->name, add_bb ? ".bb" : "");
+
+ return 0;
+}
+
+/**
+ * of_find_path_by_node - translate a node in the devicetree to a
+ * barebox device path
+ *
+ * @node: the node we're interested in
+ * @outpath: if this function returns 0 outpath will contain the path belonging
+ * to the input path description. Must be freed with free().
+ * @flags: use OF_FIND_PATH_FLAGS_BB to return the .bb device if available
+ *
+ */
+int of_find_path_by_node(struct device_node *node, char **outpath, unsigned flags)
+{
+ return __of_find_path(node, NULL, outpath, flags);
+}
+
/**
* of_find_path - translate a path description in the devicetree to a barebox
* path
@@ -134,11 +191,8 @@ out:
*/
int of_find_path(struct device_node *node, const char *propname, char **outpath, unsigned flags)
{
- struct of_path op = {};
struct device_node *rnode;
- const char *path, *str;
- bool add_bb = false;
- int i, ret;
+ const char *path;
path = of_get_property(node, propname, NULL);
if (!path)
@@ -148,37 +202,5 @@ int of_find_path(struct device_node *node, const char *propname, char **outpath,
if (!rnode)
return -ENODEV;
- op.dev = of_find_device_by_node_path(rnode->full_name);
- if (!op.dev) {
- op.dev = of_find_device_by_node_path(rnode->parent->full_name);
- if (!op.dev)
- return -ENODEV;
- }
-
- device_detect(op.dev);
-
- op.cdev = cdev_by_device_node(rnode);
-
- i = 1;
-
- while (1) {
- ret = of_property_read_string_index(node, propname, i++, &str);
- if (ret)
- break;
-
- ret = of_path_parse_one(&op, str);
- if (ret)
- return ret;
- }
-
- if (!op.cdev)
- return -ENOENT;
-
- if ((flags & OF_FIND_PATH_FLAGS_BB) && op.cdev->mtd &&
- mtd_can_have_bb(op.cdev->mtd))
- add_bb = true;
-
- *outpath = asprintf("/dev/%s%s", op.cdev->name, add_bb ? ".bb" : "");
-
- return 0;
+ return __of_find_path(rnode, propname, outpath, flags);
}
diff --git a/include/crypto/keystore.h b/include/crypto/keystore.h
new file mode 100644
index 0000000000..29915854b8
--- /dev/null
+++ b/include/crypto/keystore.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2015 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
+ *
+ * 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.
+ */
+
+#ifndef __CRYPTO_KEYSTORE_H
+#define __CRYPTO_KEYSTORE_H
+
+#ifdef CONFIG_CRYPTO_KEYSTORE
+int keystore_get_secret(const char *name, const u8 **secret, int *secret_len);
+int keystore_set_secret(const char *name, const u8 *secret, int secret_len);
+#else
+static inline int keystore_get_secret(const char *name, const u8 **secret, int *secret_len)
+{
+ return -EINVAL;
+}
+static inline int keystore_set_secret(const char *name, const u8 *secret, int secret_len)
+{
+ return 0;
+}
+#endif
+
+#endif
diff --git a/include/of.h b/include/of.h
index e0ebc39b74..e60fe89825 100644
--- a/include/of.h
+++ b/include/of.h
@@ -246,6 +246,7 @@ void of_add_memory_bank(struct device_node *node, bool dump, int r,
struct device_d *of_find_device_by_node_path(const char *path);
#define OF_FIND_PATH_FLAGS_BB 1 /* return .bb device if available */
int of_find_path(struct device_node *node, const char *propname, char **outpath, unsigned flags);
+int of_find_path_by_node(struct device_node *node, char **outpath, unsigned flags);
int of_register_fixup(int (*fixup)(struct device_node *, void *), void *context);
int of_unregister_fixup(int (*fixup)(struct device_node *, void *), void *context);
struct device_node *of_find_node_by_alias(struct device_node *root,
diff --git a/include/state.h b/include/state.h
index 08c4e8654b..b3966fd99e 100644
--- a/include/state.h
+++ b/include/state.h
@@ -17,7 +17,6 @@ struct state *state_by_name(const char *name);
struct state *state_by_node(const struct device_node *node);
int state_get_name(const struct state *state, char const **name);
-int state_load(struct state *state);
int state_save(struct state *state);
void state_info(void);